Fragment在生命周期中是如何走到onCreateView的(二)

回顾

Fragment在生命周期中是如何走到onCreateView的(一)中,主要从代码上走了一下,如何从调用replace.commit开始,走到fragment生命周期的各关键方法的。
其中比较重要的方面有:
1. FragmentManager负责控制fragment生命周期的流转,重要方法是moveToState
2. BackStackRecord负责处理和分发对fragment的一系列操作,最终会走到FragmentManager的moveToState

一般来说,我们调用fragment,用到的方法都是replace,add,remove,show,hide,attach,detach这一些,这些都是由BackStackRecord来实现的:
1. BackStackRecord首先会将这些操作封装成一个个Op。Op里包含对应的操作方式,上一个Op,下一个Op,进出动画等。

static final class Op {
        Op next;
        Op prev;
        int cmd;
        Fragment fragment;
        int enterAnim;
        int exitAnim;
        int popEnterAnim;
        int popExitAnim;
        ArrayList<Fragment> removed;

}
2. BackStackRecord将操作封装成Op之后,并不会立即执行,而是将Op放到一个双向链表中。从Op的结构也可以看出,Op是链表中的一个结点。从获取BackStackRecord的方法beginTransaction也可以看出,这里就是一个事务的概念。
3. BackStackRecord是一个Runnable,在commit之后,FragmentManager会执行Runnable的run,这时就会把链表中的Op循环一遍。
4. 对每个Op来说,根据操作类型,会分别执行到FragmentManager的addFragment,removeFragment,hideFragment,showFragment,detachFragment,attachFragment等方法
5. 之后就会进入到moveToState
以上就是对上一篇的回顾。

本文来看一下在moveToState是如何走到onCreateView的

Fragment的state

static final int INITIALIZING = 0;     // Not yet created.
static final int CREATED = 1;          // Created.
static final int ACTIVITY_CREATED = 2; // The activity has finished its creation.
static final int STOPPED = 3;          // Fully created, not started.
static final int STARTED = 4;          // Created and started, not resumed.
static final int RESUMED = 5;          // Created started and resumed.

Fragemnt的状态包括这六种,从0到5,从小到大,从initial到resume,可以看作一个状态上升的过程。相反,从5到0,则可以看到状态下降。
而在状态之间切换的时候,就会调用我们熟知的那些生命周期方法。

初始状态

在我们调用replace或者add后,都会在BackStackRecord的run中,执行

mManager.moveToState(mManager.mCurState, transition, transitionStyle, true);

最终会调用到FragmentManager的moveToState

void moveToState(Fragment f, int newState, int transit, int transitionStyle, boolean keepActive) {

具体代码就不再贴一遍了。

newState是mManager.mCurState,即是FragmentManager的state,具体是什么我还没仔细研究,应该是跟Activity的状态一致吧,如果我们实在Activity的onCreate中调用的,暂且认为是STOPPED(created, not started)

开始会有一些状态的判断,先略去。
然后会走到第一个判断。

if (f.mState < newState) {
    // 这里处理状态上升
} else if (f.mState > newState) {
    // 这里处理状态下降
}

f的状态,初始是INITIALIZING,肯定会小于STOPPED,进入状态上升的处理逻辑

接下来是switch判断

switch (f.mState) {
            case Fragment.INITIALIZING:

            case Fragment.CREATED:
                if (newState > Fragment.CREATED) {

                }
            case Fragment.ACTIVITY_CREATED:
                if (newState > Fragment.ACTIVITY_CREATED) {

                }
            case Fragment.STOPPED:
                if (newState > Fragment.STOPPED) {

                }
            case Fragment.STARTED:
                if (newState > Fragment.STARTED) {

                }
        }

可以看到,会根据fragment的state来进入相应的case。
而且,case是没有break的,也就是会一直按顺序执行到newState对应的方法。

Fragment.INITIALIZING

注意到几个语句

f.mHost = mHost;
f.mParentFragment = mParent;
f.mFragmentManager = mParent != null? mParent.mChildFragmentManager : mHost.getFragmentManagerImpl();
f.mCalled = false;
f.onAttach(mHost.getContext());
...
if (f.mParentFragment == null) {
    mHost.onAttachFragment(f);
} else {
    f.mParentFragment.onAttachFragment(f);
}
...
if (f.mFromLayout) {
    // For fragments that are part of the content view
    // layout, we need to instantiate the view immediately
    // and the inflater will take care of adding it.
    f.mView = f.performCreateView(f.getLayoutInflater(
            f.mSavedFragmentState), null, f.mSavedFragmentState);
}

给fragment赋了Host,host中就包括Activity和Context
赋了父Fragment
赋了相应的FragmentManager
执行fragment的onAttach
然后执行相应的Activity或者父Fragment的onAttachFragment
如果fragment直接是view layout的一部分,则马上执行createView。这时就会走到onCreateView

View performCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    if (mChildFragmentManager != null) {
        mChildFragmentManager.noteStateNotSaved();
    }
    return onCreateView(inflater, container, savedInstanceState);
}

这是其中一个onCreateView,但我们一般使用中,更多是另外一个,在后面。

Fragment.CREATED

if (newState > Fragment.CREATED) {
 if (!f.mFromLayout) {
     ViewGroup container = null;
     if (f.mContainerId != 0) {
         ...
         container = (ViewGroup) mContainer.onFindViewById(f.mContainerId);
         ...
     }
     f.mContainer = container;
     f.mView = f.performCreateView(f.getLayoutInflater(
             f.mSavedFragmentState), container, f.mSavedFragmentState);
     if (f.mView != null) {
         f.mInnerView = f.mView;
         ...
         if (container != null) {
             ...
             container.addView(f.mView);
         }
         if (f.mHidden) f.mView.setVisibility(View.GONE);
         f.onViewCreated(f.mView, f.mSavedFragmentState);
     } else {
         f.mInnerView = null;
     }

     f.performActivityCreated(f.mSavedFragmentState);
     if (f.mView != null) {
         f.restoreViewState(f.mSavedFragmentState);
     }
     f.mSavedFragmentState = null;
 }

首先根据containerId找到容器ViewGroup,并赋给f.mContainer
然后就是performCreateView,也就是另外一个onCreateView,这是当fragment不是view layout的一部分的情况。赋给f.mView
接着把f.mView添加到container里面
然后走fragment的onViewCreated
之后会调用fragment的performActivityCreated,里面就会走到onActivityCreated

至此,我们就找到了onCreateView

其余

剩下的几个case也会有相应的逻辑。
状态下降的过程也类似,只不过执行了相对来说相反的逻辑

最后

if (f.mState != newState) {
...
  f.mState = newState;
}

会把fragment的状态更新

小结

这里可以看到moveToState是fragment生命周期流转的关键方法。本文主要从调用add或者replace往下顺的,还有其他情况,比如当Activity生命周期发生变化时,也会走moveToState,进而让fragment走对应的生命周期方法。

问题

这里有个问题,就是FragmentManager的state变化,我并没有细究,应该是跟Activity的是一致的,本文是基于此进行的分析,后面有机会可以研究一下。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值