Fragment的创建分析

        之前的文章讨论了Fragment的销毁流程,初始状态为resume,然后经历pause -> stop -> destroyView -> destroy -> detach这么几个流程(本篇文章基于Support27.1.1来分析的)。清楚了Fragment的销毁,那也来看看Fragment的创建,这里先放一张Fragment生命周期的图,如下:

        该图包含了Fragment从创建到销毁的所有生命周期方法及与相应Activity生命周期状态的对关系,相应面试过程中如果遇到Fragment相关的问题,应该都不会逃过生命周期相关的问题。然而生命周期只是Fragment运行的表现,它是如何一步步运行起来的呢?这篇文章聚焦Fragment的创建,从源码角度分析Fragment的创建流程。

        由于Fragment的流程依附于相应Activity的生命周期,因此这里以Activity的onCreate、onStart、onResume为主线来说明Fragment的生命周期是如何转换的。

目录

1. Activity.onCreate

2. Activity.onStart

3. Activity.onResume


1. Activity.onCreate

        在Activity的onCreate执行的时候,我们的Fragment则经历了onAttach -> onCreate ->onCreateView -> onActivityCreated几个生命周期方法,下面从FragmentActivity的onCreate开始分析,老规矩上代码:

@SuppressWarnings("deprecation")
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        mFragments.attachHost(null /*parent*/);//A

        super.onCreate(savedInstanceState);

        NonConfigurationInstances nc =
                (NonConfigurationInstances) getLastNonConfigurationInstance();
        if (nc != null) {
            mViewModelStore = nc.viewModelStore;
        }
        if (savedInstanceState != null) {//B
            Parcelable p = savedInstanceState.getParcelable(FRAGMENTS_TAG);
            mFragments.restoreAllState(p, nc != null ? nc.fragments : null);

            // Check if there are any pending onActivityResult calls to descendent Fragments.
            if (savedInstanceState.containsKey(NEXT_CANDIDATE_REQUEST_INDEX_TAG)) {
                mNextCandidateRequestIndex =
                        savedInstanceState.getInt(NEXT_CANDIDATE_REQUEST_INDEX_TAG);
                int[] requestCodes = savedInstanceState.getIntArray(ALLOCATED_REQUEST_INDICIES_TAG);
                String[] fragmentWhos = savedInstanceState.getStringArray(REQUEST_FRAGMENT_WHO_TAG);
                if (requestCodes == null || fragmentWhos == null ||
                            requestCodes.length != fragmentWhos.length) {
                    Log.w(TAG, "Invalid requestCode mapping in savedInstanceState.");
                } else {
                    mPendingFragmentActivityResults = new SparseArrayCompat<>(requestCodes.length);
                    for (int i = 0; i < requestCodes.length; i++) {
                        mPendingFragmentActivityResults.put(requestCodes[i], fragmentWhos[i]);
                    }
                }
            }
        }

        if (mPendingFragmentActivityResults == null) {
            mPendingFragmentActivityResults = new SparseArrayCompat<>();
            mNextCandidateRequestIndex = 0;
        }

        mFragments.dispatchCreate();//C
    }

        上面的代码中用注释标识了A/B/C三处代码,A处相当于是Fragment运行环境的初始化,B处是状态的恢复,C处是Fragment生命周期的状态转换;我们重点看A/C两处,先看A,代码如下:

    
//FragmentActivity.java
final FragmentController mFragments = FragmentController.createController(new HostCallbacks());

    //FragmentController.java
    /**
     * Attaches the host to the FragmentManager for this controller. The host must be
     * attached before the FragmentManager can be used to manage Fragments.
     */
    public void attachHost(Fragment parent) {
        mHost.mFragmentManager.attachController(
                mHost, mHost /*container*/, parent);
    }

    //FragmentManager.java
    public void attachController(FragmentHostCallback host,
            FragmentContainer container, Fragment parent) {
        if (mHost != null) throw new IllegalStateException("Already attached");
        mHost = host;
        mContainer = container;
        mParent = parent;
    }

         调用attachHost把相关参数传递到FragmentManager中,mHost、mContainer的值都为在FragmentActivity中创建的HostCallbacks对象,mParent则为空,Activity中的第一个Fragment的mParentFragment对象总是空的,因为它就是第一个Fragment。

        mFragments.dispatchCreate()这行代码开启了Fragment生命周期的轮转,经过前面的分析我们知道最终会到FragmentManager中5个参数版本的moveToState方法中,这里简单贴下中间跳转代码:

    /**
     * Moves all Fragments managed by the controller's FragmentManager
     * into the create state.
     * <p>Call when Fragments should be created.
     *
     * @see Fragment#onCreate(Bundle)
     */
    public void dispatchCreate() {
        mHost.mFragmentManager.dispatchCreate();
    }

    public void dispatchCreate() {
        mStateSaved = false;
        mStopped = false;
        dispatchStateChange(Fragment.CREATED);//注意该值
    }

    private void dispatchStateChange(int nextState) {
        try {
            mExecutingActions = true;
            moveToState(nextState, false);
        } finally {
            mExecutingActions = false;
        }
        execPendingActions();
    }

    void moveToState(int newState, boolean always) {
        if (mHost == null && newState != Fragment.INITIALIZING) {
            throw new IllegalStateException("No activity");
        }

        if (!always && newState == mCurState) {
            return;
        }

        mCurState = newState;

        if (mActive != null) {

            // Must add them in the proper order. mActive fragments may be out of order
            final int numAdded = mAdded.size();
            for (int i = 0; i < numAdded; i++) {
                Fragment f = mAdded.get(i);
                moveFragmentToExpectedState(f);
            }

            // Now iterate through all active fragments. These will include those that are removed
            // and detached.
            final int numActive = mActive.size();
            for (int i = 0; i < numActive; i++) {
                Fragment f = mActive.valueAt(i);
                if (f != null && (f.mRemoving || f.mDetached) && !f.mIsNewlyAdded) {
                    moveFragmentToExpectedState(f);
                }
            }

            startPendingDeferredFragments();

            if (mNeedMenuInvalidate && mHost != null && mCurState == Fragment.RESUMED) {
                mHost.onSupportInvalidateOptionsMenu();
                mNeedMenuInvalidate = false;
            }
        }
    }

    void moveFragmentToExpectedState(Fragment f) {
        if (f == null) {
            return;
        }
        int nextState = mCurState;
        if (f.mRemoving) {
            if (f.isInBackStack()) {
                nextState = Math.min(nextState, Fragment.CREATED);
            } else {
                nextState = Math.min(nextState, Fragment.INITIALIZING);
            }
        }
        moveToState(f, nextState, f.getNextTransition(), f.getNextTransitionStyle(), false);//状态转换入口

        if (f.mView != null) {
            // Move the view if it is out of order
            Fragment underFragment = findFragmentUnder(f);
            if (underFragment != null) {
                final View underView = underFragment.mView;
                // make sure this fragment is in the right order.
                final ViewGroup container = f.mContainer;
                int underIndex = container.indexOfChild(underView);
                int viewIndex = container.indexOfChild(f.mView);
                if (viewIndex < underIndex) {
                    container.removeViewAt(viewIndex);
                    container.addView(f.mView, underIndex);
                }
            }
            if (f.mIsNewlyAdded && f.mContainer != null) {
                // Make it visible and run the animations
                if (f.mPostponedAlpha > 0f) {
                    f.mView.setAlpha(f.mPostponedAlpha);
                }
                f.mPostponedAlpha = 0f;
                f.mIsNewlyAdded = false;
                // run animations:
                AnimationOrAnimator anim = loadAnimation(f, f.getNextTransition(), true,
                        f.getNextTransitionStyle());
                if (anim != null) {
                    setHWLayerAnimListenerIfAlpha(f.mView, anim);
                    if (anim.animation != null) {
                        f.mView.startAnimation(anim.animation);
                    } else {
                        anim.animator.setTarget(f.mView);
                        anim.animator.start();
                    }
                }
            }
        }
        if (f.mHiddenChanged) {
            completeShowHideFragment(f);
        }
    }


        嗯,一堆堆代码了,moveToState(f, nextState, f.getNextTransition(), f.getNextTransitionStyle(), false); 最后这行代码正式进入生命周期转换当中,通过前面的分析知道分为创建和销毁两大流程,这里省略销毁流程,创建流程代码如下:

    @SuppressWarnings("ReferenceEquality")
    void moveToState(Fragment f, int newState, int transit, int transitionStyle,
            boolean keepActive) {
        // Fragments that are not currently added will sit in the onCreate() state.
        if ((!f.mAdded || f.mDetached) && newState > Fragment.CREATED) {
            newState = Fragment.CREATED;
        }
        if (f.mRemoving && newState > f.mState) {
            if (f.mState == Fragment.INITIALIZING && f.isInBackStack()) {
                // Allow the fragment to be created so that it can be saved later.
                newState = Fragment.CREATED;
            } else {
                // While removing a fragment, we can't change it to a higher state.
                newState = f.mState;
            }
        }
        // Defer start if requested; don't allow it to move to STARTED or higher
        // if it's not already started.
        if (f.mDeferStart && f.mState < Fragment.STARTED && newState > Fragment.STOPPED) {
            newState = Fragment.STOPPED;
        }
        if (f.mState <= newState) {
            //这里是创建流程 attach -> create -> creatView -> activityCreated ->
            // start -> resume
            // For fragments that are created from a layout, when restoring from
            // state we don't want to allow them to be created until they are
            // being reloaded from the layout.
            if (f.mFromLayout && !f.mInLayout) {
                return;
            }
            if (f.getAnimatingAway() != null || f.getAnimator() != null) {
                // The fragment is currently being animated...  but!  Now we
                // want to move our state back up.  Give up on waiting for the
                // animation, move to whatever the final state should be once
                // the animation is done, and then we can proceed from there.
                f.setAnimatingAway(null);
                f.setAnimator(null);
                moveToState(f, f.getStateAfterAnimating(), 0, 0, true);
            }
            switch (f.mState) {
                case Fragment.INITIALIZING:
                    if (newState > Fragment.INITIALIZING) {
                        if (DEBUG) Log.v(TAG, "moveto CREATED: " + f);
                        if (f.mSavedFragmentState != null) {
                            f.mSavedFragmentState.setClassLoader(mHost.getContext()
                                    .getClassLoader());
                            f.mSavedViewState = f.mSavedFragmentState.getSparseParcelableArray(
                                    FragmentManagerImpl.VIEW_STATE_TAG);
                            f.mTarget = getFragment(f.mSavedFragmentState,
                                    FragmentManagerImpl.TARGET_STATE_TAG);
                            if (f.mTarget != null) {
                                f.mTargetRequestCode = f.mSavedFragmentState.getInt(
                                        FragmentManagerImpl.TARGET_REQUEST_CODE_STATE_TAG, 0);
                            }
                            if (f.mSavedUserVisibleHint != null) {
                                f.mUserVisibleHint = f.mSavedUserVisibleHint;
                                f.mSavedUserVisibleHint = null;
                            } else {
                                f.mUserVisibleHint = f.mSavedFragmentState.getBoolean(
                                        FragmentManagerImpl.USER_VISIBLE_HINT_TAG, true);
                            }
                            if (!f.mUserVisibleHint) {
                                f.mDeferStart = true;
                                if (newState > Fragment.STOPPED) {
                                    newState = Fragment.STOPPED;
                                }
                            }
                        }

                        f.mHost = mHost;
                        f.mParentFragment = mParent;
                        f.mFragmentManager = mParent != null
                                ? mParent.mChildFragmentManager : mHost.getFragmentManagerImpl();

                        // If we have a target fragment, push it along to at least CREATED
                        // so that this one can rely on it as an initialized dependency.
                        if (f.mTarget != null) {
                            if (mActive.get(f.mTarget.mIndex) != f.mTarget) {
                                throw new IllegalStateException("Fragment " + f
                                        + " declared target fragment " + f.mTarget
                                        + " that does not belong to this FragmentManager!");
                            }
                            if (f.mTarget.mState < Fragment.CREATED) {
                                moveToState(f.mTarget, Fragment.CREATED, 0, 0, true);
                            }
                        }

                        dispatchOnFragmentPreAttached(f, mHost.getContext(), false);
                        f.mCalled = false;
                        f.onAttach(mHost.getContext());
                        if (!f.mCalled) {
                            throw new SuperNotCalledException("Fragment " + f
                                    + " did not call through to super.onAttach()");
                        }
                        if (f.mParentFragment == null) {
                            mHost.onAttachFragment(f);
                        } else {
                            f.mParentFragment.onAttachFragment(f);
                        }
                        dispatchOnFragmentAttached(f, mHost.getContext(), false);

                        if (!f.mIsCreated) {
                            dispatchOnFragmentPreCreated(f, f.mSavedFragmentState, false);
                            f.performCreate(f.mSavedFragmentState);
                            dispatchOnFragmentCreated(f, f.mSavedFragmentState, false);
                        } else {
                            f.restoreChildFragmentState(f.mSavedFragmentState);
                            f.mState = Fragment.CREATED;
                        }
                        f.mRetaining = false;
                    }
                    // fall through
                case Fragment.CREATED:
                    // This is outside the if statement below on purpose; we want this to run
                    // even if we do a moveToState from CREATED => *, CREATED => CREATED, and
                    // * => CREATED as part of the case fallthrough above.
                    ensureInflatedFragmentView(f);

                    if (newState > Fragment.CREATED) {
                        if (DEBUG) Log.v(TAG, "moveto ACTIVITY_CREATED: " + f);
                        if (!f.mFromLayout) {
                            ViewGroup container = null;
                            if (f.mContainerId != 0) {
                                if (f.mContainerId == View.NO_ID) {
                                    throwException(new IllegalArgumentException(
                                            "Cannot create fragment "
                                                    + f
                                                    + " for a container view with no id"));
                                }
                                container = (ViewGroup) mContainer.onFindViewById(f.mContainerId);
                                if (container == null && !f.mRestored) {
                                    String resName;
                                    try {
                                        resName = f.getResources().getResourceName(f.mContainerId);
                                    } catch (NotFoundException e) {
                                        resName = "unknown";
                                    }
                                    throwException(new IllegalArgumentException(
                                            "No view found for id 0x"
                                            + Integer.toHexString(f.mContainerId) + " ("
                                            + resName
                                            + ") for fragment " + f));
                                }
                            }
                            f.mContainer = container;
                            f.mView = f.performCreateView(f.performGetLayoutInflater(
                                    f.mSavedFragmentState), container, f.mSavedFragmentState);
                            if (f.mView != null) {
                                f.mInnerView = f.mView;
                                f.mView.setSaveFromParentEnabled(false);
                                if (container != null) {
                                    container.addView(f.mView);
                                }
                                if (f.mHidden) {
                                    f.mView.setVisibility(View.GONE);
                                }
                                f.onViewCreated(f.mView, f.mSavedFragmentState);
                                dispatchOnFragmentViewCreated(f, f.mView, f.mSavedFragmentState,
                                        false);
                                // Only animate the view if it is visible. This is done after
                                // dispatchOnFragmentViewCreated in case visibility is changed
                                f.mIsNewlyAdded = (f.mView.getVisibility() == View.VISIBLE)
                                        && f.mContainer != null;
                            } else {
                                f.mInnerView = null;
                            }
                        }

                        f.performActivityCreated(f.mSavedFragmentState);
                        dispatchOnFragmentActivityCreated(f, f.mSavedFragmentState, false);
                        if (f.mView != null) {
                            f.restoreViewState(f.mSavedFragmentState);
                        }
                        f.mSavedFragmentState = null;
                    }
                    // fall through
                case Fragment.ACTIVITY_CREATED:
                    if (newState > Fragment.ACTIVITY_CREATED) {
                        f.mState = Fragment.STOPPED;
                    }
                    // fall through
                case Fragment.STOPPED:
                    if (newState > Fragment.STOPPED) {
                        if (DEBUG) Log.v(TAG, "moveto STARTED: " + f);
                        f.performStart();
                        dispatchOnFragmentStarted(f, false);
                    }
                    // fall through
                case Fragment.STARTED:
                    if (newState > Fragment.STARTED) {
                        if (DEBUG) Log.v(TAG, "moveto RESUMED: " + f);
                        f.performResume();
                        dispatchOnFragmentResumed(f, false);
                        f.mSavedFragmentState = null;
                        f.mSavedViewState = null;
                    }
            }
        } else if (f.mState > newState) {
            //这里是销毁流程 pause -> stop -> destoroyView -> destory -> detach
        }

        if (f.mState != newState) {
            Log.w(TAG, "moveToState: Fragment state for " + f + " not updated inline; "
                    + "expected state " + newState + " found " + f.mState);
            f.mState = newState;
        }
    }

        首次进入Fragment的状态为Fragment.INITIALIZING,而前面调用dispatchCreate 时传递的状态nextState参数为Fragment.CREATED,因此newState为Fragment.CREATED,所以上面的创建流程会进入到Fragment.INITIALIZING对应的分支,这里单独拿出该分支代码如下:

    if (newState > Fragment.INITIALIZING) {
        if (DEBUG) Log.v(TAG, "moveto CREATED: " + f);
        if (f.mSavedFragmentState != null) {//A
            f.mSavedFragmentState.setClassLoader(mHost.getContext()
                    .getClassLoader());
            f.mSavedViewState = f.mSavedFragmentState.getSparseParcelableArray(
                    FragmentManagerImpl.VIEW_STATE_TAG);
            f.mTarget = getFragment(f.mSavedFragmentState,
                    FragmentManagerImpl.TARGET_STATE_TAG);
            if (f.mTarget != null) {
                f.mTargetRequestCode = f.mSavedFragmentState.getInt(
                        FragmentManagerImpl.TARGET_REQUEST_CODE_STATE_TAG, 0);
            }
            if (f.mSavedUserVisibleHint != null) {
                f.mUserVisibleHint = f.mSavedUserVisibleHint;
                f.mSavedUserVisibleHint = null;
            } else {
                f.mUserVisibleHint = f.mSavedFragmentState.getBoolean(
                        FragmentManagerImpl.USER_VISIBLE_HINT_TAG, true);
            }
            if (!f.mUserVisibleHint) {
                f.mDeferStart = true;
                if (newState > Fragment.STOPPED) {
                    newState = Fragment.STOPPED;
                }
            }
        }
        //B
        f.mHost = mHost;
        f.mParentFragment = mParent;
        f.mFragmentManager = mParent != null
                ? mParent.mChildFragmentManager : mHost.getFragmentManagerImpl();

        // If we have a target fragment, push it along to at least CREATED
        // so that this one can rely on it as an initialized dependency.
        if (f.mTarget != null) {
            if (mActive.get(f.mTarget.mIndex) != f.mTarget) {
                throw new IllegalStateException("Fragment " + f
                        + " declared target fragment " + f.mTarget
                        + " that does not belong to this FragmentManager!");
            }
            if (f.mTarget.mState < Fragment.CREATED) {
                moveToState(f.mTarget, Fragment.CREATED, 0, 0, true);
            }
        }
        //C
        dispatchOnFragmentPreAttached(f, mHost.getContext(), false);
        f.mCalled = false;
        f.onAttach(mHost.getContext());
        if (!f.mCalled) {
            throw new SuperNotCalledException("Fragment " + f
                    + " did not call through to super.onAttach()");
        }
        if (f.mParentFragment == null) {
            mHost.onAttachFragment(f);
        } else {
            f.mParentFragment.onAttachFragment(f);
        }
        dispatchOnFragmentAttached(f, mHost.getContext(), false);

        if (!f.mIsCreated) {//D
            dispatchOnFragmentPreCreated(f, f.mSavedFragmentState, false);
            f.performCreate(f.mSavedFragmentState);
            dispatchOnFragmentCreated(f, f.mSavedFragmentState, false);
        } else {
            f.restoreChildFragmentState(f.mSavedFragmentState);
            f.mState = Fragment.CREATED;
        }
        f.mRetaining = false;
    }

        上面的代码标注了A/B/C/D四处,A处主要是状态恢复,B处mHost、mParentFragment、mFragmentManager的赋值,C处调用了生命周期方法onAttach,D处则调用了onCreate,这里关注C/D两处,先看C处代码如下:

    /**
     * Called when a fragment is first attached to its context.
     * {@link #onCreate(Bundle)} will be called after this.
     */
    @CallSuper
    public void onAttach(Context context) {
        mCalled = true;
        final Activity hostActivity = mHost == null ? null : mHost.getActivity();
        if (hostActivity != null) {
            mCalled = false;
            onAttach(hostActivity);
        }
    }

        简单的调用了 onAttach而已。

tips:这里的onAttach方法有两个版本,一个是带Context参数的,一个是带Activity参数的,其实通过代码分析发现传递过来的始终是Activity对象。

        再看D处,代码如下:

    void performCreate(Bundle savedInstanceState) {
        if (mChildFragmentManager != null) {
            mChildFragmentManager.noteStateNotSaved();
        }
        mState = CREATED;
        mCalled = false;
        onCreate(savedInstanceState);
        mIsCreated = true;
        if (!mCalled) {
            throw new SuperNotCalledException("Fragment " + this
                    + " did not call through to super.onCreate()");
        }
        mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);
    }

    @CallSuper
    public void onCreate(@Nullable Bundle savedInstanceState) {
        mCalled = true;
        restoreChildFragmentState(savedInstanceState);
        if (mChildFragmentManager != null
                && !mChildFragmentManager.isStateAtLeast(Fragment.CREATED)) {
            mChildFragmentManager.dispatchCreate();
        }
    }

         也是简单回调,同时重置mIsCreated为true(避免重复调用吧),注意这里也会调用恢复子Fragment的状态。

onCreate调用完毕,Fragment的mState为CREATED,相应FragmentManager内部的mCurState为CREATED。

         Fragment的onCreate调用完毕,继续运行;switch代码穿透到Fragment.CREATED分支,这里根据Fragment和相应FragmentManager的状态对比,并不会进入该分支的if语句内部(表明当前执行到了Fragment.CREATED这个状态)。但是以下代码会执行:

void ensureInflatedFragmentView(Fragment f) {
        if (f.mFromLayout && !f.mPerformedCreateView) {
            f.mView = 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;
            }
        }
    }

        如果Fragment是在布局中加载的,这里就会创建Fragment的View了,这里假设不是,我们继续分析。

        Activity.onCreate执行完毕,发现只调用了相应Fragment的onAttach和onCreate方法,貌似与开篇上的图有差别(知道就行了,别怪我的图,我也是不知道从哪里拿来的)。 

2. Activity.onStart

        现在进入Activity的onStart方法,代码如下:

    @Override
    protected void onStart() {
        super.onStart();

        mStopped = false;
        mReallyStopped = false;
        mHandler.removeMessages(MSG_REALLY_STOPPED);

        if (!mCreated) {
            mCreated = true;
            mFragments.dispatchActivityCreated();//A
        }

        mFragments.noteStateNotSaved();
        mFragments.execPendingActions();

        // NOTE: HC onStart goes here.

        mFragments.dispatchStart();//B
    }

        关注A/B两处,这里的状态分发都会进入到FragmentManager里面5个参数的moveToState方法中,所以中间的过程省略了。

        先看A处,还是关注传递的参数,代码如下:

public void dispatchActivityCreated() {
        mStateSaved = false;
        mStopped = false;
        dispatchStateChange(Fragment.ACTIVITY_CREATED);
    }

         这里传递了Fragment.ACTIVITY_CREATED,因此FragmengManager中mCurState会变为Fragment.ACTIVITY_CREATED,但是相应Fragment的状态mState还是CREATED(即将要变为ACTIVITY_CREATED),所以进入到moveToState的Fragment.CREATED分支中,代码如下:

    // This is outside the if statement below on purpose; we want this to run
    // even if we do a moveToState from CREATED => *, CREATED => CREATED, and
    // * => CREATED as part of the case fallthrough above.
    ensureInflatedFragmentView(f);

    if (newState > Fragment.CREATED) {
        if (DEBUG) Log.v(TAG, "moveto ACTIVITY_CREATED: " + f);
        if (!f.mFromLayout) {
            ViewGroup container = null;
            if (f.mContainerId != 0) {//A
                if (f.mContainerId == View.NO_ID) {
                    throwException(new IllegalArgumentException(
                            "Cannot create fragment " + f
                                    + " for a container view with no id"));
                }
                container = (ViewGroup) mContainer.onFindViewById(f.mContainerId);
                if (container == null && !f.mRestored) {
                    String resName;
                    try {
                        resName = f.getResources().getResourceName(f.mContainerId);
                    } catch (Resources.NotFoundException e) {
                        resName = "unknown";
                    }
                    throwException(new IllegalArgumentException(
                            "No view found for id 0x"
                                    + Integer.toHexString(f.mContainerId) + " ("
                                    + resName
                                    + ") for fragment " + f));
                }
            }
            //B
            f.mContainer = container;
            f.mView = f.performCreateView(f.performGetLayoutInflater(
                    f.mSavedFragmentState), container, f.mSavedFragmentState);
            if (f.mView != null) {
                f.mInnerView = f.mView;
                f.mView.setSaveFromParentEnabled(false);
                if (container != null) {
                    container.addView(f.mView);
                }
                if (f.mHidden) {
                    f.mView.setVisibility(View.GONE);
                }
                //C
                f.onViewCreated(f.mView, f.mSavedFragmentState);
                dispatchOnFragmentViewCreated(f, f.mView, f.mSavedFragmentState,
                        false);
                // Only animate the view if it is visible. This is done after
                // dispatchOnFragmentViewCreated in case visibility is changed
                f.mIsNewlyAdded = (f.mView.getVisibility() == View.VISIBLE)
                        && f.mContainer != null;
            } else {
                f.mInnerView = null;
            }
        }

        //D
        f.performActivityCreated(f.mSavedFragmentState);
        dispatchOnFragmentActivityCreated(f, f.mSavedFragmentState, false);
        if (f.mView != null) {
            f.restoreViewState(f.mSavedFragmentState);
        }
        f.mSavedFragmentState = null;
    }

        ensureInflatedFragmentView已经分析过,不再说明; 上面的代码标记了A/B/C/D四处,这里会一一说明,A处主要是找到相应activity中Fragment的容器View,如果找不到则会抛异常。

我们通过如下代码动态添加Fragment

FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
        ft.add(R.id.container, new FragmentLifeTest(), "FragmentLifeTest")
                .commitAllowingStateLoss();

上面分析的A处其实就是找到R.id.containe对应的View(该View是相应Fragment的View的容器)

         B处把A处找到的容器保存到Fragment的mContainer成员变量中,接着调用方法performCreateView,该方法会返回Fragment对应的View视图,接着把返回的View视图添加到mContainer中(嗯,Fragment的视图还是通过操作activity中的容器添加到activity视图中的),来看下performCreateView方法,代码如下:

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

        比较简单,调用onCreateView返回Fragment对应的View,没啥说的。 

        接着分析,来到C处,调用onViewCreated,嗯,这里直接调用了Fragment的onViewCreated方法,传递了刚刚返回的Fragment对应的View,说明此时View已经创建;所以我们再写Fragment的时候通常会把UI的初始化逻辑写在onViewCreated中,这回知道原因了吧。

        最后是D处,performActivityCreated,代码如下:

    void performActivityCreated(Bundle savedInstanceState) {
        if (mChildFragmentManager != null) {
            mChildFragmentManager.noteStateNotSaved();
        }
        mState = ACTIVITY_CREATED;
        mCalled = false;
        onActivityCreated(savedInstanceState);
        if (!mCalled) {
            throw new SuperNotCalledException("Fragment " + this
                    + " did not call through to super.onActivityCreated()");
        }
        if (mChildFragmentManager != null) {
            mChildFragmentManager.dispatchActivityCreated();
        }
    }

        也是简单的调用了onActivityCreated,注意这里Fragment状态发生了改变,变为ACTIVITY_CREATED。

执行完Activity.onStart方法之后,Fragment的状态从CREATED转变为了ACTIVITY_CREATED。

        继续分析 ,CREATED分支执行完毕,代码继续运行,进入ACTIVITY_CREATED分支,经过分析,该分支条件不满足,最后退出整个switch代码块。

分析完Activity.onStart的第一部分dispatchActivityCreated,我们知道对应的Fragment主要执行了onCreateView -> onViewCreated -> onActivityCreated

        进入 Activity.onStart的第二部分dispatchStart,相关传参代码如下:

    public void dispatchStart() {
        mStateSaved = false;
        mStopped = false;
        dispatchStateChange(Fragment.STARTED);
    }

        参数为 Fragment.STARTE,则FragmentManager的mCurState会变为Fragment.STARTE,而Fragment此时还是上一个状态即:ACTIVITY_CREATED,因此执行如下代码:

    case Fragment.ACTIVITY_CREATED:
        if (newState > Fragment.ACTIVITY_CREATED) {
            f.mState = Fragment.STOPPED;
        }

        太简单了,一个瞬时状态,Fragment的状态直接变为Fragment.STOPPED了,继续分析,由于传递的nextState为Fragment.STARTE,因此进入如下代码:

    case Fragment.STOPPED:
        if (newState > Fragment.STOPPED) {
            if (DEBUG) Log.v(TAG, "moveto STARTED: " + f);
            f.performStart();
            dispatchOnFragmentStarted(f, false);
        }
        // fall through

        调用了Fragment的performStart方法,该方法代码如下:

    void performStart() {
        if (mChildFragmentManager != null) {
            mChildFragmentManager.noteStateNotSaved();
            mChildFragmentManager.execPendingActions();
        }
        mState = STARTED;
        mCalled = false;
        onStart();
        if (!mCalled) {
            throw new SuperNotCalledException("Fragment " + this
                    + " did not call through to super.onStart()");
        }
        if (mChildFragmentManager != null) {
            mChildFragmentManager.dispatchStart();
        }
        mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_START);
    }

         Fragment的状态变为了STARTED,同时调用Fragment的生命周期方法onStart。

        代码继续运行,进入到Fragment.STARTED分支,但是此时条件不满足,因此退出switch代码块。

总结起来,在activity的onSart生命周期中,相应Fragment调用了经历了:onCreateView -> onViewCreated -> onActivityCreated -> onStart。相应状态mState最终变为了Fragment.STARTED。

3. Activity.onResume

        到了Activity的onResume阶段,Fragment的创建也快完成了,Activity入口处代码如下:

    /**
     * Dispatch onResume() to fragments.  Note that for better inter-operation
     * with older versions of the platform, at the point of this call the
     * fragments attached to the activity are <em>not</em> resumed.  This means
     * that in some cases the previous state may still be saved, not allowing
     * fragment transactions that modify the state.  To correctly interact
     * with fragments in their proper state, you should instead override
     * {@link #onResumeFragments()}.
     */
    @Override
    protected void onResume() {
        super.onResume();
        mHandler.sendEmptyMessage(MSG_RESUME_PENDING);
        mResumed = true;
        mFragments.execPendingActions();
    }

        发送了一个消息去执行Fragment的resume(为啥这里要这样做呢?不太理解,希望有明白的读者不吝指教),MSG_RESUME_PENDING对应的代码如下:

    final Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case MSG_REALLY_STOPPED:
                    if (mStopped) {
                        doReallyStop(false);
                    }
                    break;
                case MSG_RESUME_PENDING:
                    onResumeFragments();
                    mFragments.execPendingActions();
                    break;
                default:
                    super.handleMessage(msg);
            }
        }

    };

    /**
     * This is the fragment-orientated version of {@link #onResume()} that you
     * can override to perform operations in the Activity at the same point
     * where its fragments are resumed.  Be sure to always call through to
     * the super-class.
     */
    protected void onResumeFragments() {
        mFragments.dispatchResume();
    }

        还是调用mFragments.dispatchResume把Activity相关的事件传递到FragmentManager中进行分发,贴出部分传参的关键代码:

    public void dispatchResume() {
        mStateSaved = false;
        mStopped = false;
        dispatchStateChange(Fragment.RESUMED);
    }

        这里传递了Fragment.RESUMED,则相应FragmentManager中的mCurState为Fragment.RESUMED,而Fragment还是上一个状态Fragment.STARTED,因此在moveToState方法中会执行如下代码:

    // fall through
    case Fragment.STARTED:
        if (newState > Fragment.STARTED) {
            if (DEBUG) Log.v(TAG, "moveto RESUMED: " + f);
            f.performResume();
            dispatchOnFragmentResumed(f, false);
            f.mSavedFragmentState = null;
            f.mSavedViewState = null;
        }

        调用perormResume,同时调用dispatchOnFragmentResumed分发resume事件,这里看看perormResume,代码如下:

    void performResume() {
        if (mChildFragmentManager != null) {
            mChildFragmentManager.noteStateNotSaved();
            mChildFragmentManager.execPendingActions();
        }
        mState = RESUMED;
        mCalled = false;
        onResume();
        if (!mCalled) {
            throw new SuperNotCalledException("Fragment " + this
                    + " did not call through to super.onResume()");
        }
        if (mChildFragmentManager != null) {
            mChildFragmentManager.dispatchResume();
            mChildFragmentManager.execPendingActions();
        }
        mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_RESUME);
    }

        修改Fragment的状态为Fragment.RESUMED,调用onResume生命周期方法,调用通过LifecycleRegistry注册的resume事件。

执行完Activity.onResume,相应的Fragment状态也变为了Fragment.RESUMED。

        到此,Fragment的创建算是完成了,从源码角度分析了activity中的生命周期对应的Fragment生命周期事件;若是你能读到这里,相信会有所收获。 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值