1、资源相关的系统配置发生改变引起
以图片资源为例,在Android项目中,为了兼容不同的设备,会在不同目录下放入不同的图片,比如drawable-mdpi、drawable-hdpi、drawable-land等。设备就会根据实际情况去加载合适的Resoures资源。假设你为横屏与竖屏放入了不同的图片,当Activity从竖屏旋转至横屏时,Activity就会被销毁并且重新创建。
这种异常终止情况下,系统会调用onSaveInstanceState来保存当前Activity状态。系统重新创建Activity之后,会把onSaveInstanceState方法所保存的Bundle对象作为参数转递给onCreate和onRestoreInstanceState来恢复以前Activity的状态。
onSaveInstanceState调用时机是在onStop之前,与onPause没有确定顺序,可能在onPause之前,也可能在onPause之后。按下Home键或跳转其它Activity,也会调用onSaveInstanceState;正常销毁时,系统不会调用onSaveInstanceState
onRestoreInstanceState调用时机是在onStart之后
注意:onRestoreInstanceState一旦被调用,其参数Bundle savedInstanceState一定有值的;而onCreate是正常启动的话,其参数Bundle savedInstanceState为null,需要额外判断。其实,这两个方法都可以进行数据恢复,任选其一就行,官方文档建议采用onRestoreInstanceState。
在onSaveInstanceState和onRestoreInstanceState方法中,系统自动为我们做了一定的恢复工作。比如文本框的数据、ListView滚动的位置等。和Activity一样,每个View都有onSaveInstanceState和onRestoreInstanceState,看一下具体实现,就能知道系统能够自动为View恢复哪些数据。
关于保存和恢复状态,系统的工作流程:Activity意外终止时,会调用onSaveInstanceState保存数据,然后Activity会委托Window去保存数据,Window会去委托它上面的顶级容器(ViewGroup,一般来说他很可能是DecorView)去保存数据,最后这顶级容器会一一通知子元素来保存数据;这是一种典型的委托思想,上层委托下层。比如View的绘制过程、事件的分发等都是采用类似的思想。
对于屏幕旋转,如果不想Activity重新创建,我们可以给Activity指定configChanges属性。这样的话,旋转屏幕,Activity就不会重新创建,取而代之是系统调用Activity的onConfigurationChanged方法。
2、资源内存不足引起
Activity的优先级情况:
a、前台Activity:正在与用户交互的Activity,优先级最高
b、可见但非前台Activity:例如Activity中弹出了一个对话框,导致Activity可见但是位于后台无法与用户交互
c、后台Activity:被暂停的Activity,比如执行了onStop,优先级最低
当系统内存不足时,系统就会根据优先级去杀死目标Activity所在的进程,并会通过onSaveInstanceState和onRestoreInstanceState来存储和恢复数据,其过程和上一节完全一致