一、典型情况下的生命周期
在正常情况下,Activity会经历如下生命周期:
1. onCreate:
表示Activity正在被创建。可以做一些初始化工作,比如调用setContentView方法去加载界面布局资源、初始化Activity所需数据等。
2. onRestart:
表示Activity从不可见变为可见。比如,用户按下home键切换到桌面或者用户打开了一个新的Activity,当前Activity的onPause方法和onStop方法会被执行,接着用户又回到这个Activity,该Activity的onRestart方法就会被执行。
3. onStart:
表示Activity已经可见但是还不能与用户交互。
4. onResume:
表示Activity已经可见并且能与用户交互。
5. onPause:
表示Activity正在停止,Activity可见但是不能与用户交互。注意不能做太耗时工作,因为这会影响到新Activity的显示(当前Activity的onPause方法必须先执行完,新Activity的onCreate、onStart、onResume才会执行)。
6. onStop:
表示Activity即将停止,Activity不可见。可以做一些稍微重量级的回收工作,同样不能太耗时。
7. onDestroy:
表示Activity即将被销毁。可以做一些回收工作和最终的资源释放。
分情况分析:
情况1. 针对一个特定的Activity,第一次启动,回调如下:
onCreate ==> onStart ==> onResume。
情况2. 当用户按下home键切换到桌面或者用户打开了一个新的Activity,当前Activity回调如下:
onPause ==> onStop。
如果新Activity采用了透明主题,那么当前Activity不会回调onStop。
情况3. 当用户再次回到原Activity时,回调如下:
onRestart ==> onStart ==> onResume。
情况4. 当用户按back键回退时,回调如下:
onPause ==> onStop ==> onDestroy。
情况5. 当Activity被系统回收后再次打开,生命周期方法回调过程和 情况1 一样,
注意是生命周期方法一样,不代表所有过程都一样,将在 "异常情况下的生命周期" 部分分析。
情况6. 从整个生命周期来说,onCreate和onDestroy是配对的,onStart和onStop是配对的,onResume和onPause是配对的。
二、异常情况下的生命周期
1. 资源相关的系统配置发生改变导致Activity被杀死并重新创建
在默认情况下,如果不对Activity做特殊处理,当系统资源配置发生改变后,Activity就会被销毁并重新创建。其onPause、onStop、onDestroy均会被调用,同时由于Activity是在异常情况下终止的,系统会调用onSaveInstanceState方法来保存当前Activity的状态。
onSaveInstanceState方法的调用时机是在onStop方法之前,它和onPause方法没有既定的时序关系,有可能在onPause方法之前,也有可能是在onPause方法之后。
当Activity被重新创建后,系统会调用onRestoreInstanceState方法,并且把Activity销毁时onSaveInstanceState方法所保存的Bundle对象作为参数同时传递给onRestoreInstanceState和onCreate方法。因此,我们可以通过onRestoreInstanceState和onCreate方法来判断Activity是否被重建了,如果被重建了,就可以取出之前保存的数据并恢复。
onRestoreInstanceState方法的调用时机是在onStart之后。
onRestoreInstanceState和onCreate方法的区别是:onRestoreInstanceState方法一旦被调用,其参数Bundle saveInstanceState一定是有值的,不用额外判空;而如果想使用onCreate方法来恢复数据,则需要判断参数Bundle saveInstanceState是否不为空。建议使用onRestoreInstanceState方法去恢复数据。
当Activity在异常情况下需要重新创建时,系统会默认为我们保存当前Activity的视图结构,并且在Activity重启后为我们恢复这些数据,比如EditText中用户输入的数据、ListView滚动的位置等,具体针对某一个特定的View系统能为我们恢复哪些数据,可以查看每个View的onSaveInstanceState和onRestoreInstanceState方法。
关于保存和恢复View层次结构,工作流程如下:
(1)Activity被意外终止,Activity会调用onSaveInstanceState去保存数据;
(2)Activity会委托Window去保存数据;
(3)Window再委托它上面的顶级容器即DecorView去保存数据;
(4)DecorView是一个ViewGroup,它会一一通知它的子元素去保存数据;
(5)如果子元素是ViewGroup,它会一一通知它的子元素去保存数据。
数据恢复过程跟数据保存过程类似。
2. 资源内存不足时导致低优先级的Activity被杀死
这个情况的数据保存和恢复过程跟"资源相关的系统配置发生改变导致Activity被杀死并重新创建"完全一致。
Activity按照优先级从高到低分为三种:
(1)前台Activity:正在和用户交互,优先级最高;
(2)可见但是无法和用户交互Activity:比如Activity中弹出了一个对话框,导致Activity可见但是无法和用户交互;
(3)后台Activity:已经被暂停的Activity,比如执行了onStop方法,优先级最低。
当系统内存不足时,会安装上述优先级去杀死目标Activity所在的进程,并在后续通过onSaveInstanceState和onRestoreInstanceState来存储和恢复数据。
如果一个进程中没有四大组件在执行,那么这个进程将很快被系统杀死,因此一些后台工作不适合脱离四大组件而独自运行在后台中,这样进程很容易被杀死,比较好的方法是将后台工作放入Service中从而保持进程有一定的优先级,这样就不会轻易被系统杀死。
3. 资源相关的系统配置发生改变时不重新创建Activity的方法
通过配置Activity的configChanges属性,当配置发生改变后Activity就不会重新创建,并且也不会调用onSaveInstanceState和onRestoreInstanceState方法来保存和恢复数据,而是会调用onConfigurationChanged方法,可以在里面做一些特殊处理。
例子:防止旋转屏幕时Activity重启
//AndroiManifest.xml
<activity android:name=".MainActivity"
android:configChanges="orientation|screenSize"> //minSdkVersion和targetSdkVersion有一个大于13,除了orientation,还要加上screenSize
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
//代码,MainActivity
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
Log.d("MainActivity", "zwm, onConfigurationChanged");
}