捋不动了的源码之Fragment的生命周期

1,387 阅读5分钟

androidx.appcompat:appcompat:1.0.2

androidx.lifecycle:lifecycle-extensions:2.2.0-alpha02

对于Fragment的生命周期,先来了解一下Fragment的state,有5种状态,默认状态为INITIALIZING

//Fragment.java
static final int INITIALIZING = 0;     // Not yet created.
static final int CREATED = 1;          // Created.
static final int ACTIVITY_CREATED = 2; // Fully created, not started.
static final int STARTED = 3;          // Created and started, not resumed.
static final int RESUMED = 4;          // Created started and resumed.

int mState = INITIALIZING;

众所周知,Fragment的生命周期其实跟Activity的生命周期是有关的,系统最终会调用到Activity的onCreate等生命周期方法,其中FragmentActivity重写了生命周期方法,在内部根据生命周期的不同,给Fragment分发不同的state状态。其实在Activity中,也有对Fragment进行state的分发,其中Fragment的状态有6种,根据猜测,这应该是在直接继承Activity的情形下出现的,现在还是关注继承AppCompatActivity情形下,Fragment的一种生命周期的表现。

在源码内,简单的分析了一下,将Activity中分发出去的状态,称之为newState,Fragment当前的状态称之为curState,先上个图

从图中可以大致得出,Activity中每一次newState的分发都会进入该判断流程中,根据发出的newState和Fragment当前的curState做判断,根据判断的结果选择状态是从上往下迁移还是从下往上迁移,每一种Fragment状态都会执行相对应的生命周期方法,在每个状态的执行最后会将curState设置为下一个状态,继续执行判断,直至一个流程结束或比较判断结果为false。主要的判断流程源码在FragmentManagerImpl内的moveToState方法。

void moveToState(Fragment f, int newState, int transit, int transitionStyle,
                 boolean keepActive) {
    ...
    //若当前fragment的状态小于等于新的状态时,比如fragment默认INITIALIZING,分发来的状态为CREATED
    if (f.mState <= newState) {
        ...
        switch (f.mState) {
            case Fragment.INITIALIZING:
                if (newState > Fragment.INITIALIZING) {
                    ...
                    //最终调用到onAttach
                    f.performAttach();
                    ...
                    //如果fragment还未create
                    if (!f.mIsCreated) {
                        dispatchOnFragmentPreCreated(f, f.mSavedFragmentState, false);
                        //调用到fragment的onCreate,并且fragment的state设置为CREATED,mIsCreated设置为true
                        f.performCreate(f.mSavedFragmentState);
                        dispatchOnFragmentCreated(f, f.mSavedFragmentState, false);
                    } else {
                        f.restoreChildFragmentState(f.mSavedFragmentState);
                        f.mState = Fragment.CREATED;
                    }
                }
             
            //由于上面的case没有执行break,继续判断,上面的case中已经将fragment的state设置为CREATED
            case Fragment.CREATED:
                //标记点1
                if (newState > Fragment.INITIALIZING) {
                    ensureInflatedFragmentView(f);
                }
            
                if (newState > Fragment.CREATED) {
                    if (!f.mFromLayout) {
                        ...
                        //走到fragment的onCreateView,内部还会创建一个LifecycleRegistry
                        f.performCreateView(f.performGetLayoutInflater(
                                f.mSavedFragmentState), container, f.mSavedFragmentState);
                        if (f.mView != null) {
                            ...
                            f.onViewCreated(f.mView, f.mSavedFragmentState);
                            ...
                        }
                        ...
                    }

                    //调用到fragment的onActivityCreated,fragment的state设置为ACTIVITY_CREATED
                    f.performActivityCreated(f.mSavedFragmentState);
                    ...
                }
                
            case Fragment.ACTIVITY_CREATED:
                if (newState > Fragment.ACTIVITY_CREATED) {
                    //调用到fragment的onStart,fragment的state设置为STARTED
                    f.performStart();
                    dispatchOnFragmentStarted(f, false);
                }
                
            case Fragment.STARTED:
                if (newState > Fragment.STARTED) {
                    //调用到fragment的onResume,fragment的state设置为RESUMED
                    f.performResume();
                    dispatchOnFragmentResumed(f, false);
                    f.mSavedFragmentState = null;
                    f.mSavedViewState = null;
                }
        }
    } else if (f.mState > newState) {
        //若新的状态小于fragment当前的状态时
        switch (f.mState) {
            case Fragment.RESUMED:
                if (newState < Fragment.RESUMED) {
                    //调用到fragment的onPause,fragment的state设置为STARTED
                    f.performPause();
                    dispatchOnFragmentPaused(f, false);
                }
                
            case Fragment.STARTED:
                if (newState < Fragment.STARTED) {
                    //调用到fragment的onStop,fragment的state设置为ACTIVITY_CREATED
                    f.performStop();
                    dispatchOnFragmentStopped(f, false);
                }

            case Fragment.ACTIVITY_CREATED:
                if (newState < Fragment.ACTIVITY_CREATED) {
                    ...
                    //调用到fragment的onDestroyView,fragment的state设置为CREATED
                    f.performDestroyView();
                    dispatchOnFragmentViewDestroyed(f, false);
                    ...
                    f.mContainer = null;
                    f.mView = null;
                    f.mViewLifecycleOwner = null;
                    f.mViewLifecycleOwnerLiveData.setValue(null);
                    f.mInnerView = null;
                    f.mInLayout = false;
                }
                
            case Fragment.CREATED:
                if (newState < Fragment.CREATED) {
                    ...
                    if (f.getAnimatingAway() != null || f.getAnimator() != null) {
                        f.setStateAfterAnimating(newState);
                        newState = Fragment.CREATED;
                    } else {
                        ...
                        if (beingRemoved || mNonConfig.shouldDestroy(f)) {
                            ...
                            //调用到fragment的onDestroy,fragment的state设置为INITIALIZING
                            f.performDestroy();
                            dispatchOnFragmentDestroyed(f, false);
                        } else {
                            f.mState = Fragment.INITIALIZING;
                        }

                        //调用到fragment的onDetach
                        f.performDetach();
                        dispatchOnFragmentDetached(f, false);
                        ...
                    }
                }
        }
    }

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

moveToState方法内,还有一个最大生命周期的判断

if (f.mMaxState == Lifecycle.State.CREATED) {
    newState = Math.min(newState, Fragment.CREATED);
} else {
    newState = Math.min(newState, f.mMaxState.ordinal());
}

表示如果Fragment设置了MaxState(Fragment可以实现的最大生命周期状态,默认为Lifecycle.State.RESUME),若设置的最大状态为Lifecycle.State.CREATED,那么只要Activity分发的newState大于CREATED,就都会被设置为CREATED,此时打开一个Activity,按照上面的流程图可以知道该Activity内部的Fragment的生命周期只会走到onCreate,关闭Activity的时候,也只有在onDestory的时候分发的INITIALIZING小于当前Fragment所在的CREATED,根据当前Fragment的状态,从上图可知,会进入onDestoryonDetach生命周期。以此类推其他最大生命周期的状态下的Fragment生命周期流程。最大生命周期可以通过FragmentTransaction来设置。

supportFragmentManager.beginTransaction().apply {
    add(R.id.fragment_content, fragment)
    setMaxLifecycle(fragment, Lifecycle.State.CREATED)
    commit()
}

并不是一开始分发newState就会进入moveToState方法的,那么它都会在什么时候被真正的调用呢,在addFragment之后。Fragment添加方式包括使用FragmentTransaction来添加以及直接在xml使用fragment标签。当使用FragmentTransaction来添加的时候,会调用commit方法,最终实现在BackStackRecord中的commitInternal内,调用到FragmentManagerImpl,通过Handler发送一个mExecCommit信息

Runnable mExecCommit = new Runnable() {
    @Override
    public void run() {
        execPendingActions();
    }
};

execPendingActions方法最终会执行到FragmentManagerImpladdFragment方法,实际上该方法在FragmentActivity中的onStartonResume去分发newState之前都会调用一次,即表示不论在onCreateonStartonResume哪个生命周期内调用commit方法,都能及时的将Fragment的INITIALIZING迁移至newState

protected void onStart() {
    super.onStart();
    mStopped = false;
    if (!mCreated) {
        mCreated = true;
        mFragments.dispatchActivityCreated();
    }
    mFragments.noteStateNotSaved();
    //here
    mFragments.execPendingActions();

    mFragmentLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_START);
    mFragments.dispatchStart();
}

从上面分析可以得出,Fragment根据在Activity的不同生命周期内去commit,会在相应的生命周期之后再去执行Fragment的moveToState,按照流程图,从onAttach开始一直到该Activity生命周期分发的newState能到达的最大状态,比如在onStart内添加Fragment(在其他生命周期内一定要注意不能重复commit)

如果采用的是直接在xml布局中使用fragment标签来添加,先看一下其生命周期流程

在LayoutInflater中,去xml中解析布局信息去创建View的时候,对于存在fragment的情况下,最终会调用到FragmentLayoutInflaterFactoryonCreateView方法,在该方法内有这么一段代码

if (fragment == null) {
    fragment = mFragmentManager.getFragmentFactory().instantiate(
            context.getClassLoader(), fname);
    fragment.mFromLayout = true;
    fragment.mFragmentId = id != 0 ? id : containerId;
    fragment.mContainerId = containerId;
    fragment.mTag = tag;
    fragment.mInLayout = true;
    fragment.mFragmentManager = mFragmentManager;
    fragment.mHost = mFragmentManager.mHost;
    fragment.onInflate(mFragmentManager.mHost.getContext(), attrs,
            fragment.mSavedFragmentState);
    //第二个参数为true,在addFragment的最后会调用moveToState方法
    //将FragmenManager记录的state作为newState
    mFragmentManager.addFragment(fragment, true);

}
...
//如果记录的state比CREATED小,那么就将Fragment迁移到CREATED状态,反之则将Fragment迁移到记录的state
if (mFragmentManager.mCurState < Fragment.CREATED && fragment.mFromLayout) {
    mFragmentManager.moveToState(fragment, Fragment.CREATED, 0, false);
} else {
    mFragmentManager.moveToState(fragment);
}

按照当前的情况,现在顶多只把INITIALIZING迁移到了CREATED,那么按照上面的流程图,这时候Fragment的生命周期应该只到onCreate才对,但是上面的打印结果却是到onViewCreated,原因就是在上面moveToState代码中的标记点1,在case Fragment.CREATED

if (newState > Fragment.INITIALIZING) {
    ensureInflatedFragmentView(f);
}

此时判断进入ensureInflatedFragmentView方法,满足了方法内的条件判断,所以继续调用了onCreateViewonViewCreated

void ensureInflatedFragmentView(Fragment f) {
    if (f.mFromLayout && !f.mPerformedCreateView) {
        f.performCreateView(f.performGetLayoutInflater(
                f.mSavedFragmentState), null, f.mSavedFragmentState);
        if (f.mView != null) {
            f.mInnerView = f.mView;
            f.mView.setSaveFromParentEnabled(false);
            if (f.mHidden) f.mView.setVisibility(View.GONE);
            f.onViewCreated(f.mView, f.mSavedFragmentState);
            dispatchOnFragmentViewCreated(f, f.mView, f.mSavedFragmentState, false);
        } else {
            f.mInnerView = null;
        }
    }
}

ok,完结撒花