Activity的生命周期和启动模式
1.1 Acitivity的生命周期全面分析
1.1.1 典型情况下生命周期
1.onCreate()
Acitivity创建的时候调用的方法,第一个执行的方法,可以在其中做setContentView家在布局、findViewById、初始化等操作。
2.onRestart()
Activity的重新启动时调用,Acitivity从不可见到可见就会调用这个方法。
3.onStart()
Activity正在启动,这时候Activity已经可见了,但是只是在后台而已。
4.onResume()
Activity已经启动,这时Acitivity已经可见,在前台,可以和用交互。
5.onPause()
Activity即将停止,一般紧接着都会调用onStop方法,这时Acitivity还可见,不可做耗时操作,因为影响新的Acitivity启动,因为当原Activity执行了onPause后新Activity才执行onCreate方法。
6.onStop()
Activity已经停止,Activity不可见,其中不可做耗时操作。
7.onDestroy()
Activity已经销毁,Acitivity关闭执行的方法。
生命周期的几种场景分析
- 1.新的Activity启动执行:onCreate–>onStart–>onResume.
- 2.开启新的Acitivity时,原Activity执行:onPause–>onStop.但是如果新开启的Activity的主题是透明,则不会调用onStop方法。
- 3.按back键执行:onPause–>onStop–>onDestroy.
- 4.在此回到原Activity执行:onRestart–>onStart–>onResume.
- 5.从整个生命周期来看,onCreate和onDestroy是配对的,分别表示着Acitivity的创建和销毁,只可能调用一次;onStart和onStop是配对的,分别表示着Activity的可见和不可见,可调用多次;onResume和onPause是配对的,分别表示着Acitivity是否在前台,可调用多次。
开启新的Acitivity时,原Acitivity和新Activity的执行顺序:原Acitivity的onPause–>新Activity的onCreate–>onStart–>onResume–>原Activity的onStop。
案例:
MainActivity.java
public class MainActivity extends Activity {
private static final String TAG = "MainActvity";
//省略
@override
protected void onPause() {
super.onPause();
Log.d(TAG,"onPause");
}
@override
protected void onStop() {
super.onStop();
Log.d(TAG,"onStop");
}
}
SecondActivity.java
public class SecondActivityextends Activity {
private static final String TAG = "SecondActivity";
@override
protected void onCreate(Bundle saveInstanceState) {
super.onCreate(saveInstanceState);
setContentView(R.layout.activity_second);
Log.d(TAG,"onCreate");
}
@override
protected void onPause() {
super.onPause();
Log.d(TAG,"onPause");
}
@override
protected void onStop() {
super.onStop();
Log.d(TAG,"onStop");
}
}
log结果:
Android官方文档对onPause的解释:不能再onPause方法中做重量级操作,因为必须onPause执行完毕以后新的Activity才能调用onResume方法,从这一点也能分析得出不能再onPause和onStop方法中不能执行耗时操作,尤其是onPause方法,也就意味着我们尽量在onStop方法中做操作,从而使得新的Activity启动快。
1.1.2 异常情况下生命周期
- 1.情景一:资源相关的系统配置发生改变导致Activity被杀死并重新创建
语言的切换和手机横竖屏的切换都会导致Activity的重启,因为他们的资源文件改变了,需要加载新的资源文件,这种情况下,如果没有做特殊处理,生命周期如下:
系统异常终止会调用onSaveInstanceState方法保存当前Activity的状态,这个方法的调用时机是在Activity进入后台(onPause)之前调用的,需要强调的是:onSaveInstanceState方法只在异常终止的时候调用。当Acitivity重新创建会调用onRestoryInstanceState方法,并且把销毁Activity时保存在onSaveInstanceState方法中的Bundle对象作为参数传递给onRestoryInstanceState和onCreate方法,重建后我们可以拿到保存的数据并恢复,在时序上onRestoryInstanceState方法在onStart方法之后调用。
在onSaveInstanceState和onRestoryInstanceState系统自动为我们做了一定的恢复工作。当Activity异常终止重新创建时,系统会默认为我们保存当前Activity的界面,并且在打开时恢复当前界面数据,比如View,ListView等,在View相关的状态系统都会为我们恢复,每个View都有onSaveInstanceState和onRestoryInstanceState方法。
保存和恢复View的工作流程:
Activity异常关闭时,Acitivity会调用onSaveInstanceState方法保存数据,并且会委托Window去保存数据,Window会再委托顶级容器来保存数据,一般顶级容器是ViewGroup(DecorVeiw),顶级容器再一一通知他的子元素来保存这些数据。
举例
日志:
2.情景二:资源内存不足导致低优先级的Activity被杀死
Activity按照优先级从高到低:前台Activity–>可见Activity(非前台)–>后台Activity。前台Activity是正在和用户交互;可见且非前台Activity是可见,但是可能弹出对话框等情况;后台Activity就是按home键切换到后台的情况。当内存不足时,会依据优先级依次杀死Activity。在这种异常情况下回调用系统会调用onSaveInstanceStatus和onRestoryInstanceState方法保存数据和恢复数据。
更改配置如何不重新创建Activity?
配置Activity的 configChanges属性,比如屏幕旋转后不想重新创建Activity就配置orientation这个值。举例:
android:configChanges="orientation | keyboardHidden"
configChanges属性表
常用属性有:local,orientation,keyboardHidden这三个选项。此处需要注意screenSize和smallestScreenSize选项,他们两个比较特殊,他的行为和编译选项有关,和运行环境无关,在Android3.2(13)之前转屏android:configChanges设置orientation值即可,但是Android13之后还需要添加screenSize,不然还会重新创建Activity,举例:
```
android:configChanges="orientation | screenSize | keyboardHidden"
```
这样异常情况下Activity不重新创建,会调用onConfigrationChanged方法,这个时候我们可以在这里做一些处理,不会调用onSaveInstanceStatus和onRestoryInstanceState函数。