前言
前面和大家分享了Activity正常情况的生命周期,这里接着上一篇博客,谈谈我对“异常情况下的Activity生命周期”的理解。
异常情况下的Activity生命周期
异常情况下的生命周期是指Activity被系统回收或者由于当前设备的Configuration(配置)发生变化从而导致Activity被销毁重建。异常情况的产生可能是当资源相关的系统配置发生改变以及系统内存不足时,Activity就有可能被杀死。
情况1:资源相关的系统配置发生改变导致Activity被杀死并重新创建
用最简单的图片来说,当我们把一张图片放drawable
目录下,就可以通过Resources
来获取这张图片。同时为了兼容不同的设备,我们可能还需要在其他一些目录放置不同的图片,比如drawable-mhdpi
、drawable-xhdpi
、drawable-xxhdpi
等。这样当应用程序启动时,系统就会根据当前设备的情况去加载合适的Resources资源,比如说横屏手机和竖屏手机会拿到两张不同的图片(设置landscape
或者portrait
状态下的图片)。比如说当前Activity处于竖屏状态,如果突然旋转屏幕,由于系统配置发生了改变,在默认情况下,Activity就会被销毁并且重新创建,当然我们也可以阻止系统重新创建我们的Activity。
防止应用在手机运行横竖屏自动切换,我们可以在AndroidManifest中设置
landscape
或者portrait
。
####异常情况下Activity重建过程
如上图所示,当系统配置发生改变后,Activity会被销毁,其onPause
、onStop
、onDestroy
都会被调用,同时由于Activity是在异常情况下终止的,系统会调用onSavaInstanceState
来保存当前Activity的状态。这个方法的调用时机是在onStop
之前,它和onPause
没有既定的时序关系,它既可能在onPause
之前调用,也可能在onPause
之后调用。但是我们需要注意的是:
onSavaInstanceState
方法只会出现在Activity被异常终止的情况下,正常情况下系统不会回调这个方法。
当Activity被重新创建后,系统会调用onSavaInstanceState
,并把Activity销毁时onSavaInstanceState
方法保存的Bundle对象作为参数同时传递给onRestoreInstanceState
和onCreate
方法。所以我们可以通过onRestoreInstanceState
和onCreate
方法来判断Activity是否被重建。如果Activity被重建了,那么我们就可以取出之前保存额数据并恢复,从时序层面来说,onRestoreInstanceState
的调用时机在onStart
之后。
注意:
- 在调用
onSavaInstanceState
和onRestoreInstanceState
方法时,系统会自动为我们做一定的恢复工作。 - 每个View都有onSaveInstanceState和onRestoreInstanceState这两个方法。
- 接收位置可以是onRestoreInstanceState和onCreate方法,区别是:onRestoreInstanceState如果被调用,参数Bundle一定是有值的,在onCreate中需要判断参数是否为null。
onSavaInstanceState
和onRestoreInstanceState
只有在Activity异常终止时才会调用来储存和恢复数据,正常销毁的Activity生命周期中不会调用,比如:旋转屏幕,按Home键,启动新Activity等。
情况2:资源内存不足导致低优先级的Activity被杀死
Activity优先级情况:
- 前台Activity——正在和用户交互的Activity,优先级最高;
- 可见但非前台Activity——Activity中弹出的对话框,导致Activity可见但无法与用户直接产生交互;
- 后台Activity——已经被暂停的Activity,比如执行了
onStop
,优先级最低。
上面是Activity的优先级情况,当系统内存不足时会根据上述的优先级去杀死目标Activity所在的进程,并在后续通过onSavaInstanceState
和onRestoreInstanceState
方法来存储和恢复数据。
注意:
如果一个进程中没有Android四大组件在执行,那么这个进程将很快被系统杀死。所有一写后台工作不适合在脱离Android四大组件而独自运行在后台中,这样进程很容易被杀死。比较好的方式是将后台工作放入Service
中保证进程有一定的优先级,这样就不会轻易被系统杀死。
看到这里,可能大家都和我一样有一个疑问:既然Activity是在被销毁时才会异常的生命周期,那么有没有办法让Activity不重新创建呢?答案是:有的,那么下面来看一下什么办法。
不让Activity重新创建
不想让Activity在屏幕旋转的时候重新创建时,我们就可以给configChanges
属性添加orientation
这个值,如下所示:
android:configChanges="orientation"
如果我们想指定多个值,可以用“|”连接起来,比如android:configChanges=”orientation|keyboardHidden”
。系统配置中所含地项目是非常多的,但是我们常用的只有locale
、orientation
和keyboardHidden
这三个选项。下面介绍一下这三个属性:
local
:设备的本地位置发生了变化,一般指切换了系统语言;keyboardHidden
:键盘的可访问性发生了变化,比如用户调出了键盘;orientation
:屏幕方向发生了变化,比如旋转了手机屏幕。
总结
这篇博客是看了任玉刚老师的《Android开发艺术探索》一书和结合网上一些优秀的技术博客写出来的,在这里感谢他们这些乐于分享的人,我要向他们学习把自己的学习心得分享出来。如果博客有不对的地方,希望看到的朋友指正。