Fragment相关源码解析三——状态保存与恢复

这一篇单独来说一说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(...);
                }
                
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值