正常生命周期
来看看最正常的Activity的启动流程:
-
启动MainActivity时调用如下:
-
这时启动SecondActivity,调用如下:
- 再次返回MainActivity
看到这个结果时,发现MainActivity的 onPause() 的方法优先于SecondActivity的 onCreate() 。也就是说新界面启动的时候,旧界面会先将 onPause() 执行完毕,所以为了不影响新界面的启动,最好不要在 onPause() 中有过多的操作。
官方文档中也说,不要在 onPause() 有重量级操作。
异常生命周期
1. 屏幕旋转
- 观察日志,当屏幕旋转的时候,Activity会先将自己销毁掉。然后重新创建这个Activity。
- 在销毁过程中,会调用Activity的 onSaveInstanceState() 方法,可以在这里存储一些数据。
- 在重建的过程中,会调用Activity的 onRestoreInstanceState() 方法。做一些数据的重新赋值。
- onSaveInstanceState() 这个方法是在 onStop() 之前执行,和onPause() 没有先后关系,既可能在onPause()之前,也可能在onPause()之后。
- onRestoreInstanceState() 方法是在onStart() 之后执行。
onSaveInstanceState() 执行的时间:
- 点击home键回到主页或长按后选择运行其他程序
- 按下电源键关闭屏幕
- 启动新的Activity
- 横竖屏切换时,肯定会执行
旋转屏幕,禁止重新创建Activity:
Android可以为不同的尺寸和横竖屏配置不同资源。
所以当Android切换了横竖屏的时候,需要加载不同的资源。
这时就必须使用新的资源重新创建Activity。
如果你不想让Activity重新创建,可以在 AndroidManifest.xml 中配置Activity。
<activity android:name=".MainActivity"
android:configChanges="orientation|screenSize" />
然后当屏幕旋转的时候,只会调用Activity的 onConfigurationChanged() 方法。
2. 内存不足导致改变
当系统的内存不足的时候,系统会按照Activity的优先级去杀死所在的进程。
进程的优先级如下:
- 前台进程:正在交互的界面
- 可见进程:可见但不是前台界面(前台界面是透明主题等等)
- 服务进程:不属于以上两种,但是包含服务的进程
- 后台进程:一个最普通的Activity按下了Home键,会导致onStop()方法执行,就会变成后台进程
- 空进程:不属于以上种类,就是这类了。
内存不足时候引发的系统将进程杀死,如果这个进程是包含Activity,那么这个Activity的数据的存储和恢复都和上面的流程是一致的,都是调用 onSaveInstanceState() 和 onRestoreInstanceState() 方法来存储和恢复数据。
所以一个进程上没有包含四大组件,是很容易被系统杀死的。
所以后台数据处理最好使用Service去进行,以保证一定的优先级。
3. Activity持久化存储
这是 API 21 以后,才有的新特性。
新增了三个方法,每个方法都多了一个参数 PersistableBundle:
onCreate(Bundle savedInstanceState, PersistableBundle persistentState)
onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState)
onRestoreInstanceState(Bundle savedInstanceState, PersistableBundle persistentState)
文档对 PersistableBundle 的描述:是一个键值对的集合,可以安全的将数据存储到磁盘并从磁盘恢复。
所以实现这几个方法,程序会具有系统关机重启后数据恢复的能力。
想要使得这三个方法被调用,必须在AndroidManifest.xml 中做配置:
<activity
android:name=".MainActivity"
android:persistableMode="persistAcrossReboots" />
我在一开始使用AS写代码时候,经常会写错方法,发现明明实现了onCreate(),界面上却是空白的。
仔细一看才发现复写的onCreate()是两个参数的方法。
所以一定要注意,** 默认情况下这两个参数的 onCreate() 是不会被调用的**,如果写错了,界面上会是空白,并且不会报错。
但是这个功能我实验了很多次,但是 并没有成功。也不知是使用的方法不对还是手机的原因。所以有哪个大神对于这个有正确使用方法,麻烦告知我一下。
网友评论