Android开发艺术探索-Activity的生命周期和启动模式
1. 生命周期
(1)正常的生命周期
onCreate()
onStart(),onRestart()
onResume()
onPause()
onStop()
onDestroy()
下图为Android Developers官网的图:
activity_lifecycle.png
注:A 打开 B,则先执行 A 的 onPause,再执行 B 的 onResume。所以在 onPause 中不可以做耗时操作。
(2)异常情况下的生命周期
在 Activity 被异常销毁时,onSaveInstanceState 和 onRestoreInstanceState 会被调用,下面记录可能发生的异常情况:
-
系统配置发生变化导致 Activity 被杀死并重新创建
比如横竖屏切换,View 的 onSaveInstanceState 会帮我们保存一部分数据,具体会保存哪些可以在每个 View 的 onSaveInstanceState 中查看。(EditText 会保存已经输入的文本,ListView 会保存目前查看的处于的位置) -
Activity 由于内存不足被回收
Activity 分为:
前台,正在交互;
可见(如弹出对话框的 Activity);
后台,比如执行了 onStop();
在内存不足时根据优先级来决定杀死目标 Activity 所在的进程。为了更好地保活,把后台工作放在 Service 中可以保证进程有一定的优先级。
以上分析了异常的情况,那么在配置发生改变的情况下,有没有办法让 Activity 不重建呢?答案在 configChanges 配置中,
如:android:configChanges="orientation|screenSize"
上行配置指定后,则在屏幕旋转时则不会重新创建 Activity,也不会调用 onSaveInstanceState 和 onRestoreInstanceState,只会调用onConfigrationChanged。
注:当 minSdkVersion 和 targetSdkVersion 大于13时,屏幕发生旋转时为防止 Activity 重启,还需加上 screenSize。
2. Activity 的四种启动模式:
(1) standard
标准启动模式。添加一个 Activity 在该栈的栈顶,如A启动了B,B就会处于A所在的栈。
所以,如果用 Application 去启动 Activity 的话,就会报错 Calling startActivity from outside of an Avtivity context requires the FLAG_ACTIVITY_NEW_TASK,因为非 Activity 的 Context 并没有栈。解决办法:为待启动 Activity 指定 FLAG_ACTIVITY_NEW_TASK,这样启动时就会给它创建一个新的栈,不过这样做也就是 singleTask 方式启动了。
(2) singleTop
栈顶复用模式,如果要启动的 Activity 位于栈顶,启动则不会创建新的 Activity,并且会调用 onNewIntent 方法,onCeate 和 onStart 方法不会被调用。
(3) singleTask
栈内复用模式,如果要启动一个 Activity,首先看是否存在它想要的栈,如果不存在,则创建一个栈并 push 该 Activity,如果存在,则看栈内是否有该 Activity 的实例,如果没有,则创建实例并 push,否则,找到这个 Activity,clearTop,并回调 onNewIntent 方法。
(4) singleInstance
单实例模式,除了具有 singleTask 的特点,还独自占据一个栈。
注:之前面试遇到一个问题,可不可以用 singleTask 实现 singleInstance 的效果,这里想到是否是用 singleTask 方式启动,但是为其指定一个单独的栈。