Android笔记—Activity
- 资料来源如下
- 第一行代码(第二版)
Activity基础
Activity定义
- Activity 是Android四大组件之一,用户可与其提供的屏幕进行交互,以执行操作。 每个 Activity 都会获得一个用于绘制其用户界面的窗口。窗口可以充满屏幕,也可浮动。应用通常由多个彼此联系的 Activity 组成。应用中的某个 Activity 为“主”Activity,即首次启动应用时的Activity。
创建Activity
新建FirstAtivity继承自AppCompatActivity
1
2
3
4
5public class FirstActivity extends AppCompatActivity{
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
} }切换到first-layout
1
2
3
4
5
6
7
8
9
10
11<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="@+id/button_1"
android:text="button_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>在FirestActivity中加载layout
在onCreate中加入1
setContentView(R.layout.first_layout);
在AndroidMainfest文件中注册。
1
2
3
4
5
6
7
8<activity
android:name=".FirstActivity"
android:label="This is FirstActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
使用Toast
Toast google官方说明
推送一个短小信息推送给用户
如图(摘自android developer)使用方法
1
2Toast.makeText(context, text, duration).show();
举例
1
2Toast.makeText(FirstActivity.this, "you clicked button 1", Toast.LENGTH_SHORT).show();
/* activity.this 消息内容 显示时间设置 */
使用Menu
创建菜单
- 在res下新疆menu文件夹,右击menu文件夹—new—Menu resource file,创建main的菜单文件。
- main.xml中添加如下代码这里创建了两个菜单项 Add和Remove
1
2
3
4
5
6
7
8
9
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/add_item"
android:title="Add"/>
<item
android:id="@+id/remove_item"
android:title="Remove"/>
</menu> - 在FirestActivity中重写 onCreateOptionsMenu()方法(快捷键 Ctrl+O)
1
2
3
4
5
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main, menu);
return true;
}getMenuInflater()
可以得到MenuInflater对象,再调用.inflate就可以创建菜单。.inflat接受俩个参数,一是资源文件名,二是菜单项添加至那个对象中。onCreateOptionsMenu方法中返回true表示创建菜单并显示。 - 效果如下。
创建菜单点击响应事件
- 重写onOptionsItemSelected方法通过item.getItemId()判断点击选项,弹出不同的Toast
1
2
3
4
5
6
7
8
9
10
11
12
13
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.add_item:
Toast.makeText(this, "Add", Toast.LENGTH_SHORT).show();
break;
case R.id.remove_item:
Toast.makeText(this, "Remove", Toast.LENGTH_SHORT).show();
break;
default:
}
return true;
}
- 重写onOptionsItemSelected方法
向一个activity 并传递字符串
构建一个Intent
Intent intent = new Intent(this, DisplayMessageActivity.class);
构造方法有两个参数:
Context 是第一个参数,这里使用了this是因为Activity是Context的子类。
Class 类是系统将要分发的APP组件,在这里,这个Activity将会被启动。public void sendMessage(View view) { // 创建一个新的intent对象,绑定DisplayMessageActivity Intent intent = new Intent(this, DisplayMessageActivity.class); //创建一个editText对象,绑定xml中editText EditText editText = (EditText) findViewById(R.id.edit_message); //获取editText中输入文字,转成字符串 String message = editText.getText().toString(); //一个Intent对象可以携带被称为extras的键值对。 // putExtra()方法将键放在第一个参数中,将值放在第二个参数中。 intent.putExtra(EXTRA_MESSAGE, message); //启动intent对应Activity startActivity(intent); } <!--code9-->
返回数据给上一个Activity
构建Intent使用startActivityForResult()方法传入请求码,启动下一个Activity
在下一个Activity中构建Intent,intent.putExtra存入键值-key,调用setResult()方法,传入finish()结束掉Activity
重写第一个Activity中的onActivityResult()方法,调用.getStringExtra取出key对应键值。startActivityForResult(Intent, int Bundle) Intent与单纯启动Activity的Intent相同,第二个是请求码,下一级 回调提供相同的请求码,以便您应用可以正确识别结果。
1
2Intent intent = new Intent(FirestActivity.this,ScendActivity.class);
startActivityForResult(intent,1);setResult()方法,第一个参数向上级方法处理结果,一般使用RESULT_OK或RESULT_CANCELED,第二个参数 对应Intent
1
2
3
4
5
6
7//新建显示Intent
Intent intent = new Intent();
//存入key-键值
intent.putExtra("data_return","Hello Firest");
setResult(RESULT_OK,intent);
//结束Activity
finish();onActivityResult()三个参数.第一个startActivityForResult() 传递的请求代码。第二个 Activity 指定的结果代码。成功是 RESULT_OK;失败,则是 RESULT_CANCELED。第三个是传送结果数据的 Intent。
1
2
3
4
5
6
7
8
9
10
11
12
13
protected void onActivityResult(int requestCode,int resultCode,Intent data){
//选择不同请求码对应处理逻辑
switch(requestCode){
case 1:
//处理结果时候ok
if(resultCode == RESULT_OK){
//取出数据
String returnedData = data.getStringExtra("data_return");
Log.d("FirstActivity", returnedData);
}
}
}
Activity生命周期
- Activity 3种状态
- Resumed/继续
Activity 处于前台,且用户可以与其交互 - Paused/暂停
Activity 被在前台中处于另一个 Activity—部分阻挡。 暂停的 Activity 不会接收用户输入并且无法执行任何代码。 - Stopped/停止
Activity完全隐藏,对用户完全不可见.当停止时,activity的所有状态信息比如成员变量都会被保留,但是不能再执行任何代码
- Resumed/继续
启动一个Activity
- onCreate方法
- 主Activity:
- 用户点击app图标,启动主Activity
- 在AndroidManifest.xml中声明
1
2
3
4<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
- 通过调用onCreate方法创建一个Activity实例,onCreate方法在Activity的整个生命周期中只执行一次。
- 之后系统会很快的调用onStart和onResume方法,Activity进入Resumed/继续模式。直到被其他activity覆盖/屏幕关闭。
销毁Activity
- onDestory方法
大多数的APP不需要实现这个方法,因为本地类引用会随着Activity一起总结,不过Activity的清理工作应该放在onPause下或者onStop。 - Note:
在所有的情况下系统调用onDestory方法之后已经调用过onPause方法与onStop方法,不过有一个例外情况:你在onCreate方法中调用了finish方法。在一些例子中,当你的Activity临时决定要启动另一个Activity,你可能要在onCreate方法内调用finish方法来销毁这个Activity,在这种情况下,系统会立即调用onDestory方法,而不会调用其它任何生命周期方法。
暂停Activity
- onPause()方法
- Activity被其他Activity覆盖/失去用户焦点,系统调用onPause()方法,Activity 进入暂停状态。
- note:android7.0及以上版本加入了多窗口模式,当Activity失去用户焦点时,可能处于多窗口模式。
- onPause() 常用回调:
- 检查 Activity 是否可见。不可见则停止可能消耗 CPU 的操作
- 提交未保存的更改,仅保存用户离开时希望永久性保存此类更改(比如电子邮件草稿)。
- 释放系统资源,GPS/Camer等
- 示例 (释放Camer)
1
2
3
4
5
6
7
8
9public void onPause() {
super.onPause(); // Always call the superclass method first
// Release the Camera because we don't need it when paused
// and other activities might need to use it.
if (mCamera != null) {
mCamera.release();
mCamera = null;
} - 注意事项:
- 在onPause()一般不执行永久性存储用户更改,不执行 CPU 密集型工作,这些工作一般放在onStop() 。
继续 Activity
- onResume() 方法
- 暂停状态回到继续状态,Activity第一次启动时也会调用这个方法。
- onResume() 以初始化在 onPause() 期间释放的组件。
- 示例(重新获取Camera)
1
2
3
4
5
6
7public void onResume() {
super.onResume(); // Always call the superclass method first
// Get the Camera instance as the activity achieves full user focus
if (mCamera == null) {
initializeCamera(); // Local method to handle camera init
}
停止 Activity
note:
大多数相对简单的 Activity 而言,系统在 Activity 停止时会将Activity 实例保留在系统内存中,无需实现 onStop() 和 onRestart() 或甚至onStart() 方法。可能只需使用 onPause() 暂停正在进行的操作,并从系统资源断开连接。onStop() 方法
场景:
- 用户在最近应用切换到另一个应用
- 应用中执行开始新 Activity 的操作
- Activity使用时,接打电话
调用时,Activity不再可见,释放几乎所有用户不使用时不需要的资源。如果系统内存紧张,则可能销毁内存中的Acitivity实例。
onStop() 方法调用后,Activity不再可见,极端情况下,系统可能会仅终止应用进程,而不调用 onDestroy() ,因此需要使用 onStop() 释放几乎所有用户不使用时不需要的资源。
尽管 onPause() 方法在 onStop()之前调用,在onStop() 执行更大、占用更多 CPU 的关闭操作,比如向数据库写入信息
示例(草稿笔记内容保存在永久存储)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16protected void onStop() {
super.onStop(); // Always call the superclass method first
// Save the note's current draft, because the activity is stopping
// and we want to be sure the current note progress isn't lost.
ContentValues values = new ContentValues();
values.put(NotePad.Notes.COLUMN_NAME_NOTE, getCurrentNoteText());
values.put(NotePad.Notes.COLUMN_NAME_TITLE, getCurrentNoteTitle());
getContentResolver().update(
mUri, // The URI for the note to update.
values, // The map of column names and new values to apply to them.
null, // No SELECT criteria are used.
null // No WHERE columns are used.
);
}
启动/重启 Activity
- onStart() 方法
- Activity 停止转换为继续状态时,系统回调onRestart() 方法+ onStart() 方法.onStop() 方法清理了所有 Activity 的资源,重启 Activity 需要重新实例化它们。同时 Activity 初次创建时重新实例化它们。 出于此,经常使用 onStart() 方法作为 onStop() 方法的对应
- 示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
protected void onStart() {
super.onStart(); // Always call the superclass method first
// The activity is either being restarted or started for the first time
// so this is where we should make sure that GPS is enabled
LocationManager locationManager =
(LocationManager) getSystemService(Context.LOCATION_SERVICE);
boolean gpsEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
if (!gpsEnabled) {
// Create a dialog here that requests the user to enable GPS, and use an intent
// with the android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS action
// to take the user to the Settings screen to enable GPS when they click "OK"
}
}
protected void onRestart() {
super.onRestart(); // Always call the superclass method first
// Activity being restarted from stopped state
}
保存 Activity 状态
onSaveInstanceState()方法
默认情况下,Activity 实例被销毁时系统会使用 Bundle 实例状态保存 Activity 布局中有关每个 View 对象的信息。在Activity 重建时,布局状态便自动恢复先前的状态。
默认实现保存有关 Activity 视图层次的状态信息,例如 EditText 小部件中的文本或ListView 的滚动位置
要恢复的更多信息,需要重写 onSaveInstanceState()方法,将键值对添加至 Bundle 对象
note:
旋转屏幕时,Activity 将被销毁并重新创建。原因:方向更改时可能需要时加载备用资源(比如布局)示例
1
2
3
4
5
6
7
8
9
10
11
12
13static final String STATE_SCORE = "playerScore";
static final String STATE_LEVEL = "playerLevel";
...
public void onSaveInstanceState(Bundle savedInstanceState) {
// Save the user's current game state
savedInstanceState.putInt(STATE_SCORE, mCurrentScore);
savedInstanceState.putInt(STATE_LEVEL, mCurrentLevel);
// Always call the superclass so it can save the view hierarchy state
super.onSaveInstanceState(savedInstanceState);
}
恢复 Activity
- onCreate() 和 onRestoreInstanceState() 回调方法均接收包含实例状态信息的相同 Bundle
- onCreate() 方法
- 调用onCreate() 方法需要区分是创建 Activity 的新实例还是恢复先前的实例,判断 Bundle 是否为 null
- 示例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); // Always call the superclass first
// Check whether we're recreating a previously destroyed instance
if (savedInstanceState != null) {
// Restore value of members from saved state
mCurrentScore = savedInstanceState.getInt(STATE_SCORE);
mCurrentLevel = savedInstanceState.getInt(STATE_LEVEL);
} else {
// Probably initialize members with default values for a new instance
}
...
} - onRestoreInstanceState()方法
- 只需要恢复的已保存的状态
- 示例
1 | public void onRestoreInstanceState(Bundle savedInstanceState) { |
重启Activity其他选择
- 官方说明
- 重启应用并恢复大量数据不仅成本高昂,而且会留下糟糕的使用体验,有两个其他选择
在配置变更期间保留对象
- Activity 因配置变更而重启,则可通过保留 Fragment 来减轻重新初始化 Activity 的负担
- 当 Android 系统因配置变更而关闭 Activity 时,不会销毁已标记为要保留的 Activity 的片段。 您可以将此类片段添加到 Activity 以保留有状态的对象。
Activity最佳实践
知晓当前运行的活动
自定义BaseActivity继承自AppCompatActivity
重写onCreate方法,打印当前运行的Activity名
app类所有Activity改为继承BaseActivity代码如下
1
2
3
4
5
6
7public class BaseActivity extends AppCompatActivity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//打印当前类名
Log.d("BaseActivity", getClass().getSimpleName());
}效果如下
随时退出程序
- 新建ActivityCollector类作为活动管理器,添加/删除Activity登记,在BaseActivity中添加对应代码。
- 代码如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20public class ActivityCollector {
//新建Activity的列表对象
public static List<Activity> activities = new ArrayList<>();
//添加Activity进入列表
public static void addActivity(Activity activity) {
activities.add(activity);
}
//在列表中移除Activity
public static void removeActivity(Activity activity) {
activities.remove(activity);
}
//for循环列表 结束所有Activity
public static void finishAll() {
for (Activity activity : activities) {
if (!activity.isFinishing()) {
activity.finish();
}
}
}
} - BaseActivity
在onCreate()方法中添加重写onDestroy()方法1
2//Activity管理器中添加新的活动
ActivityCollector.addActivity(this);1
2
3
4
5
6
protected void onDestroy(){
super.onDestroy();
//Activity管理器中移除活动
ActivityCollector.removeActivity(this);
} - 在任何地方调用finishAll()方法即可。
启动活动的最近写法
- 启动下一个Activity并传递数据模块化
- 在SecondActivity内增加actionStart()方法
1
2
3
4
5
6
7
8
9
10//调用的Activity,数据1,数据2
public static void actionStart(Context context, String data1, String data2){
//新建Intent,绑定SecondActivity
Intent intent = new Intent(context,ScendActivity.class);
//存入data1,data2
intent.putExtra("param1",data1);
intent.putExtra("param2",data2);
//启动Activity
context.startActivity(intent);
} - 启动SecondActivity方式
ScendActivity.actionStart(FirestActivity.this,"data1","data2");