这一篇单独来说一说Fragment的状态保存和恢复。
状态保存
只要Activity不是被主动finish的,状态的保存与恢复机制就会被触发,包括 :Activity因为内存不足被killed、其他命令杀死进程、手机配置改变导致的Activity重建(用户没有手动处理配置改变的情况下)。导致onSaveInstanceState(在onStop之前)和onRestoreInstanceState(在onStart之后)的回调。而配置的改变还会在onDestroy之前引发Activity的另一个回调onRetainNonConfigurationInstance()。这两个回调相互独立,所保存的内容也不相同。
onSaveInstanceState
onSaveInstanceState方法的参数outState是一个Bundle对象,是系统保存状态时持久化状态的容器,在该方法中会调用 Parcelable p = mFragments.saveAllState() ,Fragment的状态以Parcelable的形式保存在outState中。
//FragmentActivity.java
protected void onSaveInstanceState(Bundle outState) {
...
Parcelable p = mFragments.saveAllState();
if (p != null) {
outState.putParcelable(FRAGMENTS_TAG, p);
}
...
}
保存的内容
既然调用了mFragments的saveAllState(),我们看一下这个方法总体上做了什么事情。mFragments是一个FragmentController对象,它持有Activity的很多信息,负责管理Fragment,它对Fragment的控制最终也是由FragmentManagerImpl这个类实现的。方法大部分省略了,最后我们可以看到,新建了一个FragmentManagerState,并对其3个成员赋值,FragmentManagerState对象保存了FragmentManagerImpl对象中的基本信息,作为一个可序列化的对象交给系统。
//FragmentManagerImpl.java
Parcelable saveAllState() {
.....
FragmentManagerState fms = new FragmentManagerState();
fms.mActive = active;
fms.mAdded = added;
fms.mBackStack = backStack;
return fms;
}
//FragmentManagerState.java
final class FragmentManagerState implements Parcelable {
FragmentState[] mActive;
int[] mAdded;
BackStackState[] mBackStack;
...
}
mActive成员
看一下fms.mActive,它是一个FragmentState[](对应着FragmentManagerImpl#mActive),FragmentState和Fragment在同一个包中,实现了Parcelable接口,对应着一个Fragment实例,保存了Fragment的一些状态,我们看一下它的成员就知道,分为两类,一类是tag、arguments、mRetainInstance这样的变量,还有一类是Bundle mSavedFragmentState,它用来保存一些其他的状态。这两类信息足以代表一个Fragment的状态,FragmentState把它们都封装了起来。
//FragmentState.java
final String mClassName;
final int mIndex;
final boolean mFromLayout;
final int mFragmentId;
final int mContainerId;
final String mTag;
final boolean mRetainInstance;
final boolean mDetached;
final Bundle mArguments;
Bundle mSavedFragmentState;
Fragment mInstance;
我们看下FragmentManagerImpl具体是怎样将Fragment的状态保存在FragmentState中的,还是在saveAllState() 方法中
- FragmentState fs = new FragmentState(f);
前面说的第一类基本变量 fs.mSavedFragmentState = saveFragmentBasicState(f);
前面说的第二类其他状态- 调用Fragment的onSaveInstanceState(保存用户自己需要保存的变量),同时将saveAllState()分发给子FragmentManager,完成了状态保存的分发。
- 保存Fragment的View树状态
- 保存了用户可见性状态mUserVisibleHint
如果f.mTarget不空,保存相关状态
//FragmentManagerImpl.java
Parcelable saveAllState() {
...
if (mActive == null || mActive.size() <= 0) {
return null;
}
int N = mActive.size();
FragmentState[] active = new FragmentState[N];
...
for (int i=0; i<N; i++) {
//遍历FragmentManagerImpl的mActive成员
Fragment f = mActive.get(i);
if (f != null) {
if (f.mIndex < 0) {
throwException(new IllegalStateException(...);
}