Activity状态的保存和恢复
Activity被killed或者配置发生变化前会调用onSaveInstanceState (Bundle)
来保存Activity状态以便在onCreate(Bundle)
或onRestoreInstanceState(Bundle)
中恢复。正常的生命周期中onSaveInstanceState (Bundle)
和onRestoreInstanceState(Bundle)
是不会被调用。
onSaveInstanceState (Bundle)
是在onStop()
前调用,但是无法保证和onPause()
的调用顺序。onRestoreInstanceState(Bundle)
的调用发生在onStart()
和onPostCreate(Bundle)
中间。
onSaveInstanceState (Bundle)
的默认实现是通过调用Activity布局中的每个设置了android:id
属性的View的onSaveInstanceState (Bundle)
来保存每个View的状态。然后在onRestoreInstanceState(Bundle)
中根据对应的id恢复View的状态。
所以,View状态要能够保存和恢复,需要满足两点:
- 在
onSaveInstanceState (Bundle)
和onRestoreInstanceState(Bundle)
中保存和恢复状态。 - 设置了
android:id
以便根据id恢复View状态。
TextView不仅需要设置android:id
还需要设置android:freezesText="true"
才能保存状态。查看TextView的onSaveInstanceState (Bundle)
方法,当变量mFreezesText
为true
时才会保存TextView的状态。
Activity状态的保存和恢复过程如下:
所以,对于Activity的成员变量需要我们自己手动保存和恢复。
private int countCanRestored = 0;
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("countCanRestored", countCanRestored);
}
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
countCanRestored = savedInstanceState.getInt("countCanRestored", 0);
...
}
复制代码
Fragment状态的保存和恢复
当系统资源不足导致Fragment被销毁或者配置发生变化时,Fragment状态的保持和恢复跟Activity类似。
Activity状态的保存和恢复过程如下:
onSaveInstanceState(Bundle)
方法却没有
onRestoreInstanceState(Bundle)
方法。对应地,Fragment是在
onCreate(Bundle)
,
onCreateView(LayoutInflater, ViewGroup, Bundle)
,
onActivityCreated(Bundle)
方法中恢复View状态和成员变量。需要注意的是Bundle可能为空,使用前需要判断一下。
下面考虑两种比较特殊的情况:
setRetainInstance(true);
当配置发生变化时,Fragment不会随着Activity的消毁而消毁,Fragment的实例还是存在的,只是onDestroyView()
方法被调用,View被销毁了。Fragment的成员变量和View状态都会被系统自动保存和恢复。onSaveInstanceState(Bundle)
和onActivityCreated(Bundle)
和onCreateView(LayoutInflater, ViewGroup, Bundle)
方法会被调用。onCreate(Bundle)
不会被调用。- Fragment从Activity的
back stack
中恢复。Fragment的实例并没有被销毁,只是onDestroyView
方法被调用,View被销毁了。Fragment的成员变量和View状态都会被系统自动保存和恢复。onSaveInstanceState
和onCreate(Bundle)
没有被调用。onActivityCreated(Bundle)
和onCreateView(LayoutInflater, ViewGroup, Bundle)
方法会被调用。
所以保持和恢复Activity和Fragment状态的正确姿势是:
- 确保需要保存和恢复状态的View重写了
onSaveInstanceState (Bundle)
和onRestoreInstanceState(Bundle)
这个两个方法。有的View还需要手动开启这项功能,比如TextView需要设置android:freezesText="true"
。当我们使用第三方自定义View时需要确保是否已经实现了这两个方法。如果没有,可以继承这个View,重写这个两个方法。我们自己自定义View的时候也要记得实现这两个方法。 - 给需要保存和恢复状态的View设置
android:id
。 - 保存和恢复Activity和Fragment的实例变量。
Reference:inthecheesefactory.com/blog/fragme…