《Android开发艺术探索》读书笔记之Activity的生命周期和启动模式
目录:
Activity的生命周期
Activity的启动模式
说到Activity的生命周期,相信很多人都熟悉,但是深入了解后,发现还是有很多需要注意的细节。这里将生命周期分为两种情况,一种是典型情况下的生命周期,一种是异常情况下的生命周期。
onStart():Activity已经可见了,但是还没有出现在前台,无法和用户进行交互。 onStart、onStop和onResume、onPause的区别: onStart、onStop是从Activity是否可见来回调的,而onResume、onPause是从Activity是否位于前台来回调的。
(1)资源相关的系统配置发生改变导致Activity被杀死并重新创建
例如:默认情况下,横竖屏的切换会导致Activity被销毁并重新创建,生命周期为onCreate -> onStart -> onResume -> onSaveInstanceState(和onPause没有确定的时序关系) -> onStop -> onDestroy -> onCreate -> onStart -> onRestoreInstanceState -> onResume。
关于保存和恢复View层次结构,系统的工作流程是:首先,Activity被意外终止时,Activity会调用onSaveInstanceState保存数据,然后,Activity会委托Window保存数据,接着Window再委托它上面的顶级容器(是一个ViewGroup,一般是一个DecorView)保存数据,最后,顶级容器再一一通知子元素保存数据,整个数据保存过程就完成了。
可以看到Activity中的onCreate和onRestoreInstanceState中都有Bundle savedInstanceState参数,说明可以在这两个方法中都可以恢复数据,但这两者是有区别的,它们的区别是:onRestoreInstanceState一旦被调用,其参数savedInstanceState一定有值,不需要进行额外的判断;但是onCreate不行,如果是正常启动的话,onCreate中savedInstanceState为null,所以必须额外判断。
如果不希望在横竖屏切换时重新创建Activity,可以给Activity指定configChanges属性。
常用的属性值有:
设置了Activity的属性configChanges,屏幕切换时如果Activity没有重新创建,则不会调用onSavedInstanceState和onRestoreInstanceState方法,而是会调用onConfigurationChanged方法,通过它的参数newConfig.orientation可以获取屏幕的方向代号。
(2)资源内存不足导致低优先级的Activity被杀死
Activity按照优先级从高到低依次为:
当系统内存不足时,系统会按照Activity优先级去杀死Activity所在的进程。这种情况和情况一同样用onSaveInstanceState和onRestoreInstanceState来保存和恢复数据。
Activity的四种启动模式就不一一阐述了,从问题入手来深入了解启动模式。
当我们用ApplicationContext启动standard模式的Activity的时候会报错,错误为:
android.util.AndroidRuntimeException:Calling startActivity from outside of an Activity context requires the
FLAG_ACTIVITY_NEW_TASK flag. Is this really what you want?
这是因为standard模式的Activity默认会进入启动它的Activity所属的任务栈中,但由于非Activity类型的Context并没有所谓的任务栈,所以会报这个错误。
解决方法:为待启动的Activity指定FLAG_ACTIVITY_NEW_TASK标记位,这样在启动时就会为它创建一个新的任务栈,这时启动Activity实际上是以singleTask模式启动的。
TaskAffinity属性主要和singleTask启动模式或者allowTaskReparenting属性配对使用,在其他情况下没有意义,TaskAffinity意思是任务相关性,这个参数标识了一个Activity所需要的任务栈的名字,默认情况下,所有Activity所需的任务栈的名字为应用的包名。
当TaskAffinity和allowTaskReparenting结合使用的时候,当一个应用A启动了应用B的某个非MainActivity得Activity后,如果B这个Activity的allowTaskReparenting属性为true,那么当应用B被启动后,此Activity会直接从应用A的任务栈转移到应用B的任务栈中。
分为前台任务栈和后台任务栈,后台任务栈中的Activity处于暂停状态,用户可以通过切换将后台任务栈再次调到前台。
通过看任务栈信息理解了《当前Activity》中第一行代表的正是任务栈,第二行代表当前类的全路径。
标记位的作用很多,有的可以设定Activity的启动模式,有的可以影响Activity的运行状态。
历史Activity列表是什么?
如果调出的Activity只是一个功能片段,并没有实际的意义,也没有必要出现在长按Home键调出最近使用过的程序类表中,那么使用FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS,所以历史 Activity列表可以理解为一个Activity栈,如果设置这个属性后,该Activity不会被保存在这个栈当中。