作为一个Android应用开发人员, 自不必说, Activity是我们应用的门面, 我们90%的工作都围绕它进行, 用它来呈现内容, 用它来与用户交互…
那么我们真的了解Activity吗? 它到底怎么来, 又怎么没的呢? 它是怎么加载布局, 怎么呈现内容的呢? 它们之间是如何交互的呢??? 太多的问题.
让我们先从Activity的生命周期开始我们的探索之旅吧.
1, 疑问
- Activity生命周期回调有哪些? 分别对应做什么?
- Back和Home键退出Activity有什么区别?
- 切换屏幕会发生什么? 怎么处理?
- 从Activity A启动Activity B会发生什么? 再从B启动A呢?
2, 探索
带着这些疑问, 开始我们的探索吧.
首先, 我们根据官方文档中的Activity生命周期图:
写一个简单的Demo程序, 有AActiviy和BActivity两个Activity, 分别都有两个按钮, 启动A和B. 然后在二者的各个生命周期和其他对外回调中加上log信息. 做如下几个实验, 查看log输出.
Demo源码已上传github, 源码地址.
以下实验中, AActivity和BActivity的启动模式均为标准模式. 关于launch mode, 后续会结合task和back stack来一起探索.
2.1, 正常启动Activity, Back退出, 再回来
首先, 我们看下正常启动AActivity的log输出:
可以看出果然如lifecycle图所示, onCreate – onStart – onResume 的线路创建了一个新的AActivity实例 AActivity@429ea620.
Back退出:
点击back键时, 依照 onPause – onStop – onDestroy 的顺序AActivity@429ea620销毁了.
注意: 退出时并没有调用onSaveInstanceState.
再回来:
很明显, 是一个新的AActivity实例AActivity@4295cd70创建了.
2.2, Home退出, 再回来
点击Home键的log输出:
没有onDestory, 且调用了onSaveIInstanceState.
再回来:
因为没有销毁, 所以再次进入时走restart流程, onRestart – onStart – onResume.
2.4, 旋转屏幕
我们旋转以下手机屏幕看看会发生什么:
可以看到AActivity销毁重建了~~
注意: 这里在销毁重建的过程中, 销毁时调用了onSaveInstanceState, 而重建时调用了onRestoreInstanceState.
我们在manifest文件中给AActivity加上configChanges属性:
xml
<activity
android:name=".lifecycle.AActivity"
android:label="A-Activity"
android:configChanges="orientation|keyboardHidden|screenSize">
</activity>
再试下:
请忽略AActivity的hash码. 可以看到这次AActivity在转屏时并没有重建, 而是调用了onConfigurationChanged.
2.5, A, B之间的切换
1, 从A发起一个Intent启动B
1, 新启动了一个BActivity的实例.
2, AActivity的onPause之后才开始启动BActivity.
3, BActivity的onResume之后, AActivity才调用onStop.
2, 从B再发起一个Intent启动A
会再新建一个AActivity的实例, 而非使用原来的实例(因为我们的launch mode是默认的标准模式).
流程和A启动B完全一样.
3, 从B按Back键到A
1, AActivity@429dadb0重启了
2, BActivity销毁了.
3, 和A启动B类似, B onPause之后A 重启, A重启完onResume之后, B onStop – onDestroy.
结论
- Activity的生命周期如官方图所示, 从onCreate – onStart – onResume 创建, 对应onPause – onStop – onDestory销毁.
这六个关键回调构成三个区间:
- 完整生命期: onCreate – onDestory
- 可见周期: onStart – onStop
- 可操作周期: onResume – onPause
Back键会销毁Activity, Home键Activity会进入Stop状态.
- onSaveInstanceState和onRestoreInstanceState不是生命周期回调, 不是必须调用的.
- 可以理解为onSaveInstanceState是系统认为可能会因为内存不够或是Configuration改变等销毁Activity时用来存储Activity状态的, 故而在Back键销毁时Activity并不会调用onSaveInstanceState, 因为系统认为这是用户主动销毁的.
- 对于转屏的处理, 我们可以在onSaveInstanceState和onRestoreInstanceState中处理Activity重建的状态恢复. 或是配置configChanges属性, 在onConfigurationChanges处理Configuration变化.
- 从A启动B时(或者说Activity切换时), 是A的onPause执行完, 才会开始B的onCreate, 所以要避免在onPause回调中执行耗时操作, 以免切换不流畅.
以上的生命周期分析, 实际上是Activity的较为简单的表现, 实际场景中会结合Activity的launch mode, taskAffinity, activity属性, Intent flag等综合考虑.