android Activity 生命周期详解

目录 [−]

  1. onContentChanged
  2. onPostCreate、onPostResume
  3. onPause、 onStop
  4. onCreate、 onStart
  5. onSaveInstanceState、 onRestoreInstanceState
  6. 首次启动
  7. 按下返回按键
  8. 按Home键
  9. 再次打开
  10. 屏幕旋转
  11. FirstActivity打开SecondActivity
  12. onSaveInstanceState
  13. onRestoreInstanceState

张奇 写的关于Activity生命周期的文章。
关于Activity的生命周期网上也有很多文章,最经典的莫过于官方的一张图解了。

这张图列出了Activity生命周期最主要的一些方法,启动后依次执行:

onCreate --> onStart --> onResume --> onPause --> onStop --> onDestroy

相信很多人也都已经知道以上方法与执行顺序,但是Activity还有其他方法,如onContentChanged, onPostCreate, onPostResume, onConfigurationChanged, onSaveInstanceState, onRestoreInstanceState,没有什么比自己做个Demo亲自试验研究下更有说服力了,下面我做了一个Demo来彻底研究下这些生命周期的方法,建议大家也亲自试验下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
public class DemoActivity extends Activity {
static final String TAG = DemoActivity.class.getSimpleName();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG, "onCreate");
setContentView(R.layout.activity_demo);
}
@Override
public void onContentChanged() {
super.onContentChanged();
Log.d(TAG, "onContentChanged");
}
public void onStart() {
super.onStart();
Log.d(TAG, "onStart");
}
public void onRestart() {
super.onRestart();
Log.d(TAG, "onRestart");
}
public void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
Log.d(TAG, "onPostCreate");
}
@Override
public void onResume() {
super.onResume();
Log.d(TAG, "onResume");
}
public void onPostResume() {
super.onPostResume();
Log.d(TAG, "onPostResume");
}
public void onPause() {
super.onPause();
Log.d(TAG, "onPause");
}
public void onStop() {
super.onStop();
Log.d(TAG, "onStop");
}
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "onDestroy");
}
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
Log.d(TAG, "onConfigurationChanged");
}
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
Log.d(TAG, "onSaveInstanceState");
}
public void onRestoreInstanceState(Bundle outState) {
super.onRestoreInstanceState(outState);
Log.d(TAG, "onRestoreInstanceState");
}
}

程序启动运行并结束上述生命周期的方法执行顺序是这样的:

onCreate --> onContentChanged --> onStart --> onPostCreate --> onResume --> onPostResume --> onPause --> onStop --> onDestroy

onContentChanged

onContentChanged()是Activity中的一个回调方法
当Activity的布局改动时,即setContentView()或者addContentView()方法执行完毕时就会调用该方法, 例如,Activity中各种View的findViewById()方法都可以放到该方法中。

onPostCreate、onPostResume

onPostCreate方法是指onCreate方法彻底执行完毕的回调,onPostResume类似,这两个方法官方说法是一般不会重写,现在知道的做法也就只有在使用ActionBarDrawerToggle的使用在onPostCreate需要在屏幕旋转时候等同步下状态,Google官方提供的一些实例就是如下做法:

1
2
3
4
5
6
7
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
// Sync the toggle state after onRestoreInstanceState has occurred.
mDrawerToggle.syncState();
}

onPause、 onStop

这里顺便再提一下onPause、 onStop的区别, onPause是在整个窗口被半遮盖或者半透明的时候会执行,而onStop则是在整个窗口被完全遮盖才会触发, 触发onStop的方法之前必定会触发onPause方法。

onCreate、 onStart

onCreate方法会在第一次创建的时候执行,紧接着便会执行onStart方法,之后页面被完全遮挡会执行onStop方法,再返回的时候一般便会执行onRestart --> onStart方法, 但是如果如果这时候App内存不够需要更多的内存的时候,App便会杀死该进程,结束掉该Activity,所以这时候再返回的时候便会重新执行onCreate --> onStart --> onResume方法。

onSaveInstanceState、 onRestoreInstanceState

这是一个比较深入的话题,后面会单独来讲。

下面结合一些特定的使用场景来分析下Activity的生命周期。

首次启动

onCreate --> onStart --> onResume

按下返回按键

onPause --> onStop --> onDestroy

按Home键

onPause --> onSaveInstanceState --> onStop

再次打开

onRestart --> onStart --> onResume

屏幕旋转

  • 如果你不做任何配置

启动Activity会执行如下方法:

onCreate --> onStart --> onResume

之后旋转屏幕,则Activity会被销毁并重新创建,之后便会执行如下方法:

onPause --> onSaveInstanceState --> onStop --> onDestroy --> onCreate --> onStart --> onRestoreInstanceState --> onResume

  • 在AndroidManifest配置文件里声明android:configChanges属性

默认屏幕旋转会重新创建,当然可以通过在配置文件里加上如下代码:

1
android:configChanges="keyboardHidden|orientation|screenSize"(sdk>13时需加上screenSize)

这个时候再旋转屏幕便不会销毁Activity,这时候再旋转屏幕可以看到只会执行onConfigurationChanged方法,有什么在屏幕旋转的逻辑可以重写这个方法:

1
2
3
4
5
6
public void onConfigurationChanged(Configuration newConfig) {
if (newConfig.orientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {
// TODO:
}
super.onConfigurationChanged(newConfig);
}

FirstActivity打开SecondActivity

FirstActivity打开SecondActivity,这时候FirstActivity生命周期的方法是这样的: onPause --> onSaveInstanceState --> onStop, 这个时候在SecondActivity按返回键,FirstActivity会有以下集中情况:

  • 正常情况下会执行: onRestart -> onStart -> onResume

  • 当系统由于要回收内存而把 activity 销毁时

Activity在onPause或者onStop状态下都有可能遇到由于突发事件系统需要回收内存,之后的onDestroy方法便不会再执行,这时候会执行: onCreate --> onStart --> onRestoreInstanceState --> onResume

下面介绍onSaveInstanceState和onRestoreInstanceState这两个方法。

onSaveInstanceState

onSaveInstanceState字面理解就是保存实例的状态,当某个activity变得“容易”被系统销毁时,该activity的onSaveInstanceState就会被执行,除非该activity是被用户主动销毁的,例如当用户按BACK键的时候。

注意上面的双引号,何为“容易”?言下之意就是该activity还没有被销毁,而仅仅是一种可能性。这种可能性有这么几种情况:

  • 1、当用户按下HOME键时

这是显而易见的,系统不知道你按下HOME后要运行多少其他的程序,自然也不知道activity A是否会被销毁,故系统会调用onSaveInstanceState,让用户有机会保存某些非永久性的数据。以下几种情况的分析都遵循该原则

  • 2、长按HOME键,选择运行其他的程序时。

  • 3、按下电源按键(关闭屏幕显示)时。

  • 4、从activity A中启动一个新的activity时。

  • 5、屏幕方向切换时,例如从竖屏切换到横屏时。

在屏幕切换之前,系统会销毁activity A,在屏幕切换之后系统又会自动地创建activity A,所以onSaveInstanceState一定会被执行

总而言之,onSaveInstanceState的调用遵循一个重要原则,即当系统“未经你许可”时销毁了你的activity,则onSaveInstanceState会被系统调用,这是系统的责任,因为它必须要提供一个机会让你保存你的数据(当然你不保存那就随便你了)。

onRestoreInstanceState

onSaveInstanceState字面理解就是恢复实例的状态, 需要注意的是,onSaveInstanceState方法和onRestoreInstanceState方法“不一定”是成对的被调用的,onRestoreInstanceState被调用的前提是,activity A“确实”被系统销毁了,而如果仅仅是停留在有这种可能性的情况下,则该方法不会被调用,例如,当正在显示activity A的时候,用户按下HOME键回到主界面,然后用户紧接着又返回到activity A,这种情况下activity A一般不会因为内存的原因被系统销毁,故activity A的onRestoreInstanceState方法不会被执行。

不过大多数情况下也是很少使用onRestoreInstanceState方法的,经常我们还是在onCreate方法里直接恢复状态的,onCreate方法里本身会有一个Bundle参数的,很多时候我们是这样使用的。(onCreate在onStart之前调用,而onRestoreInstanceState是在onStart之后调用)

1
2
3
4
5
6
7
8
9
10
protected void onSaveInstanceState(Bundle savedInstanceState) {
super.onSaveInstanceState(icicle);
savedInstanceState.putLong("param", value);
}
public void onCreate(Bundle savedInstanceState) {
if (savedInstanceState != null){
value = savedInstanceState.getLong("param");
}
}