一直对Activity的各种生命周期方法、创建和销毁时机以及Activity的4种启动模式没有彻底的了解清楚,详细整理记录一下这些知识,以后哪再不清楚时不会再到处查阅资料了。
首先,从网上拷过来一张图片,对这张图片,相信很多人都非常熟悉,它包括了Activity从创建到销毁的全部过程,如下图所示:
1、Activity的创建与销毁
- 从Activity的创建开始说起,当启动一个Activity时,生命周期方法调用:
onCreate()→onStart()→onResume()
此时,Activity显示在前台界面和用户交互,开始运行
从Activity点击Back键回到桌面,生命周期方法调用:
onPause()→onStop()→onDestroy()
此时,Activity被销毁,这是最常见的创建与销毁流程
在当前Activity点击Home键回到桌面,Activity进入后台运行,再次启动该Activity,生命周期方法调用:
onPause()→onStop()→onRestart()→onStart()→onResume()
如果在Activity点击Back键退出Activity,并且在当前Activity的onStop()方法还没有被调用之前,再次启动Acitivity,生命周期方法调用:
onPause()→onResume()
这种情况属于很极端的情况,在正常的用户操作下很难重现这一场景。
- 从当前Activity启动一个新的Activity:
当前显示的Activity为A,要启动的Activity为B,生命周期方法调用:
Activity A的onPause()→Activity B的onCreate()→Activity B的onStart()→Activity B的onResume()→Activity A的onStop()→Activity A的onDestroy()
此时,Activity A被销毁,Activity B显示到前台。如果Activity B的主题是透明主题,则Activity A不会被销毁,即Activity A的onStop()和onDestroy()不会被执行
可以看到,Activity A的onPause()方法执行完毕后,Activity B才会被创建,所以在onPause()方法中不可以有特别耗时的操作,否则将会影响新Activity的显示
2、Activity重新创建时数据的保存与恢复
由于资源内存不足或者系统配置发生变化导致Activity被销毁时,需要保存Activity中的数据,例如在Activity界面启动新的Activity、在Activity界面接到来电,在回到前一个Activity时,希望可以恢复原来的效果,这时就需要在Activity销毁时保存必要的数据,以便再次启动时恢复。
- 通过Activity的onSaveInstanceState()和onRestoreInstanceState()来保存和恢复数据
Activity被异常终止时,系统会调用onSaveInstanceState()方法来保存当前Activity的状态,调用时机在onStop()方法之前,和onPause()方法没有既定的时序关系,尽管大多数情况下都是在onPause()方法之后调用。onSaveInstanceState()方法接受一个Bundle参数,用于保存数据。
在这里,就用手机切换横竖屏时的场景进行测试,手机在由横屏切换到竖屏时,Activity会进行销毁并重新创建,如果不进行处理,界面上的数据就不会保存。
重写Activity的生命周期方法和onSaveInstanceState()、onRestoreInstanceState()方法并打印log。
public class MainActivity extends ListActivity {
public static final String TAG = "MainActivity";
private List<String> datas = new ArrayList<String>();
private ArrayAdapter<String> adapter;
Handler handler = new Handler() {
public void handleMessage(android.os.Message msg) {
initAdapter();
};
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.i(TAG, "onCreate");
new Thread() {
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
for(int i = 0; i < 10; i ++) {
datas.add("This is test item " + i);
}
Log.i(TAG, "loadData");
handler.sendEmptyMessage(0x123);
};
}.start();
}
public void initAdapter() {
adapter = new ArrayAdapter<String>(MainActivity.this, android.R.layout.simple_list_item_1, datas);
setListAdapter(adapter);
}