Android-Fragment的生命周期處理源碼分析

從FragmentActivity開始分析:

在FragmentActivity中有一個FragmentController對象mFragments痕支,該對象的創(chuàng)建和初始化如下:

final FragmentController mFragments = FragmentController.createController(new HostCallbacks());

1.HostCallbacks的初始化

new HostCallbacks()的操作其實很簡單铛嘱,HostCallbacks是FragmentActivity的內(nèi)部類娜遵,是繼承自FragmentHostCallback的俘侠,而new HostCallbacks最終是調(diào)用到了FragmentHostCallback的構(gòu)造器。FragmentHostCallback的構(gòu)造器其實就是保存了相應(yīng)的上下文對象种玛,創(chuàng)建了Handler曹洽,該Handler是用來進(jìn)行異步提交處理Runnable任務(wù)的。

FragmentHostCallback(@Nullable Activity activity, @NonNull Context context,
        @NonNull Handler handler, int windowAnimations) {
    mActivity = activity;
    mContext = Preconditions.checkNotNull(context, "context == null");
    mHandler = Preconditions.checkNotNull(handler, "handler == null");
    // mWindowAnimations其實是等于0
    mWindowAnimations = windowAnimations;
}

在創(chuàng)建HostCallbacks對象的時候蹭沛,其父類FragmentHostCallback又會創(chuàng)建一個FragmentManager對象mFragmentManager臂寝,其實現(xiàn)類是FragmentManagerImpl章鲤。

2.FragmentController#createController

FragmentController的對象創(chuàng)建其實很簡單,其構(gòu)造器是私有的咆贬,所有通過靜態(tài)方法創(chuàng)建败徊。

public static FragmentController createController(@NonNull FragmentHostCallback<?> callbacks) {
    return new FragmentController(checkNotNull(callbacks, "callbacks == null"));
}

3.FragmentActivity#onCreate

FragmentActivity作為Activity的生命周期開始位置,則也會通過mFragments這個FragmentController對象進(jìn)行生命周期的分發(fā)素征,然后執(zhí)行Fragment的生命周期

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    mFragments.attachHost(null /*parent*/);
    // 這里是狀態(tài)恢復(fù)的情況下才會執(zhí)行
    if (savedInstanceState != null) {
        // 從內(nèi)存中取出狀態(tài)保存是保存的數(shù)據(jù)
        Parcelable p = savedInstanceState.getParcelable(FRAGMENTS_TAG);
        mFragments.restoreSaveState(p);

        // 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;
    }

    super.onCreate(savedInstanceState);

    mFragmentLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);
    // 向FragmentController分發(fā)生命周期事件
    mFragments.dispatchCreate();
}

4.FragmentController#attachHost

public void attachHost(@Nullable Fragment parent) {
    // 這里的mHost是FragmentHostCallback的子類對象集嵌,mFragmentManager
    // 是FragmentManager對象,其實現(xiàn)類是FragmentManagerImpl
    // 這里會初始化FragmentManager中的mContainer容器對象御毅,該勇氣是在Fragment創(chuàng)建
    // ContentView的時候使用的根欧,因為該
    mHost.mFragmentManager.attachController(
            mHost, mHost /*container*/, parent);
}

5.FragmentManager#attachController

這里其實就是做一定的數(shù)據(jù)綁定,把對應(yīng)的Fragment端蛆、還有HostCallbacks等于FragmentManager做綁定凤粗,不過這里的mParent是為null的。因為在FragmentActivity傳入的時候就是傳的null

void attachController(@NonNull FragmentHostCallback<?> host,
        @NonNull FragmentContainer container, @Nullable final Fragment parent) {
    if (mHost != null) throw new IllegalStateException("Already attached");
    mHost = host;
    mContainer = container;
    mParent = parent;
    if (mParent != null) {
        // 這里取決于是否依賴有導(dǎo)航的Fragment
        updateOnBackPressedCallbackEnabled();
    }
    // 設(shè)置點擊backPressed的回調(diào)
    if (host instanceof OnBackPressedDispatcherOwner) {
        OnBackPressedDispatcherOwner dispatcherOwner = ((OnBackPressedDispatcherOwner) host);
        mOnBackPressedDispatcher = dispatcherOwner.getOnBackPressedDispatcher();
        LifecycleOwner owner = parent != null ? parent : dispatcherOwner;
        mOnBackPressedDispatcher.addCallback(owner, mOnBackPressedCallback);
    }

    // 獲取對應(yīng)的FragmentManager的視圖模型
    if (parent != null) {
        mNonConfig = parent.mFragmentManager.getChildNonConfig(parent);
    } else if (host instanceof ViewModelStoreOwner) {
        ViewModelStore viewModelStore = ((ViewModelStoreOwner) host).getViewModelStore();
        mNonConfig = FragmentManagerViewModel.getInstance(viewModelStore);
    } else {
        mNonConfig = new FragmentManagerViewModel(false);
    }
}

6.FragmentController#dispatchCreate

FragmentController中的很多操作今豆,其實都是通過HostCallbacks中的mFragmentManager對象嫌拣,調(diào)用到FragmentManager或者FragmentManagerImpl中對應(yīng)的方法。

public void dispatchCreate() {
    // 調(diào)用FragmentManager#dispatchCreate方法
    mHost.mFragmentManager.dispatchCreate();
}

7.FragmentManager#dispatchCreate

其實FragmentManager中有許多分發(fā)生命周期的方法呆躲,比如dispatchActivityCreated异逐,就是在FragmentActivity中的onStart中調(diào)用,在dispatchStart之前插掂,這些dispatch方法分發(fā)生命周期灰瞻,其實最終都是調(diào)用到了一個方法:dispatchStateChange。只不過傳入的參數(shù)不同辅甥,用來代表不同的生命周期時期酝润。

void dispatchCreate() {
    // mStateSaved是表示狀態(tài)保存的標(biāo)志。只有在保存狀態(tài)的時候才會設(shè)置為true
    mStateSaved = false;
    mStopped = false;
    // 在onCreate中調(diào)用的璃弄,就是傳入Fragment.CREATED
    // 如果實在onStart中調(diào)用的要销,則會傳入的是Fragment.ACTIVITY_CREATED和
    // Fragment.STARTED
    dispatchStateChange(Fragment.CREATED);
}

在Fragment中,最新的AndroidX的版本夏块,只有六個狀態(tài):

static final int INITIALIZING = -1;    // Not yet attached.
static final int ATTACHED = 0;         // Attached to the host.
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.

8.FragmentManager#dispatchStateChange

這里其實主要就是調(diào)用了moveToState方法疏咐,在FragmentActivity調(diào)用FragmentController的對應(yīng)的dispatch分發(fā)生命周期給Fragment的時候,最終都是調(diào)用了dispatchStateChange脐供,而dispatchStateChange最終又是調(diào)用到了moveToState

private void dispatchStateChange(int nextState) {
    try {
        mExecutingActions = true;
        // 向狀態(tài)管理器中設(shè)置Fragment的下一個狀態(tài)
        // FragmentStore中會存儲當(dāng)前FragmentActivity中的Fragment
        // 這里的moveToState移動Fragment的狀態(tài)凳鬓,會針對當(dāng)前FragmentActivity中
        // 的所有的Fragment來進(jìn)行
        mFragmentStore.dispatchStateChange(nextState);
        moveToState(nextState, false);
    } finally {
        mExecutingActions = false;
    }
    // 這是執(zhí)行事務(wù)提交的操作的。
    // 在分發(fā)生命周期的時候患民,有可能有需要提交的事務(wù)
    execPendingActions(true);
}

9.FragmentStore#dispatchStateChange

void dispatchStateChange(int state) {
    // 取出該Fragment的狀態(tài)管理器缩举,保存該Fragment的當(dāng)前狀態(tài)
    for (Fragment f : mAdded) {
        // 這里的mWho其實是Fragment對應(yīng)的唯一標(biāo)識
        FragmentStateManager fragmentStateManager = mActive.get(f.mWho);
        if (fragmentStateManager != null) {
            fragmentStateManager.setFragmentManagerState(state);
        }
    }

    // 遍歷當(dāng)前所有活躍的Fragment,設(shè)置狀態(tài)
    for (FragmentStateManager fragmentStateManager : mActive.values()) {
        if (fragmentStateManager != null) {
            fragmentStateManager.setFragmentManagerState(state);
        }
    }
}

10.FragmentManager#moveToState

將Fragment的狀態(tài)修改為newState,如果FragmentManager修改狀態(tài)或者always為true的話仅孩,則其他任何的Fragment也會改變狀態(tài)

void moveToState(int newState, boolean always) {
    if (mHost == null && newState != Fragment.INITIALIZING) {
        throw new IllegalStateException("No activity");
    }
    // 如果always=false托猩,并且當(dāng)前狀態(tài)與新的狀態(tài)一致,則不進(jìn)行任何修改
    if (!always && newState == mCurState) {
        return;
    }

    mCurState = newState;

    // 從Fragment存儲中取出所有已經(jīng)添加的Fragment辽慕,進(jìn)行遍歷
    for (Fragment f : mFragmentStore.getFragments()) {
        moveFragmentToExpectedState(f);
    }

    // 取出所有活躍的Fragment京腥,包括已經(jīng)刪除和分離的Fragment
    for (Fragment f : mFragmentStore.getActiveFragments()) {
        if (f != null && !f.mIsNewlyAdded) {
            moveFragmentToExpectedState(f);
        }
    }
    // 對延遲啟動的Fragment進(jìn)行狀態(tài)修改
    // 這里是遍歷FragmentStore中的mActive,取出活躍Fragment
    // 判斷Fragment的mDeferStart是否為true
    startPendingDeferredFragments();

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

11.FragmentManager#moveFragmentToExpectedState

將Fragment移動到最新的狀態(tài)或者是FragmentStore中FragmentStateManager中的狀態(tài)溅蛉,具體要取決于FragmentStore中的狀態(tài)是否正確觸發(fā)公浪。
本方法是由moveToState(int newState, boolean always)遍歷觸發(fā),可能會調(diào)用多次船侧,如果存在多個fragment的話欠气。

void moveFragmentToExpectedState(@NonNull Fragment f) {
    if (!mFragmentStore.containsActiveFragment(f.mWho)) {
        if (isLoggingEnabled(Log.DEBUG)) {
            Log.d(TAG, "Ignoring moving " + f + " to state " + mCurState
                    + "since it is not added to " + this);
        }
        return;
    }
    // 將Fragment狀態(tài)移動到當(dāng)前最新的狀態(tài)
    // 這里最終調(diào)用到
    moveToState(f);

    if (f.mView != null) {
        // Move the view if it is out of order
        Fragment underFragment = mFragmentStore.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:
            FragmentAnim.AnimationOrAnimator anim = FragmentAnim.loadAnimation(
                    mHost.getContext(), mContainer, f, true);
            if (anim != null) {
                if (anim.animation != null) {
                    f.mView.startAnimation(anim.animation);
                } else {
                    anim.animator.setTarget(f.mView);
                    anim.animator.start();
                }
            }
        }
    }
    // 完成對Fragment的show或者h(yuǎn)ide操作
    if (f.mHiddenChanged) {
        completeShowHideFragment(f);
    }
}

12.FragmentManager#moveToState(Fragment f, int newState)

本方法與上面的moveToState并不相同,是上面方法的重載镜撩。不要混淆预柒。
在這里改變Fragment狀態(tài)的同時,會執(zhí)行Fragment對應(yīng)的生命周期方法袁梗,比如onCreate宜鸯、onStart、onResume遮怜、onPause等方法淋袖。

void moveToState(@NonNull Fragment f, int newState) {
    // 設(shè)置該Fragment的狀態(tài)管理器
    FragmentStateManager fragmentStateManager = mFragmentStore.getFragmentStateManager(f.mWho);
    if (fragmentStateManager == null) {
        // Ideally, we only call moveToState() on active Fragments. However,
        // in restoreSaveState() we can call moveToState() on retained Fragments
        // just to clean them up without them ever being added to mActive.
        // For these cases, a brand new FragmentStateManager is enough.
        fragmentStateManager = new FragmentStateManager(mLifecycleCallbacksDispatcher, f);
        // Only allow this FragmentStateManager to go up to CREATED at the most
        fragmentStateManager.setFragmentManagerState(Fragment.CREATED);
    }
    // 對比傳入的newState和Fragment狀態(tài)管理器中的狀態(tài)哪個更小,取出更小的狀態(tài)
    newState = Math.min(newState, fragmentStateManager.computeMaxState());
    // 如果當(dāng)前Fragment的狀態(tài)小于新的狀態(tài)
    // Fragment中的狀態(tài)有6個锯梁,當(dāng)當(dāng)前Fragment的狀態(tài)小于新的狀態(tài)的時候
    // 則需要向下依次增大當(dāng)前Fragment的狀態(tài)即碗,將當(dāng)前Fragment的狀態(tài)設(shè)置為
    // 當(dāng)前狀態(tài)的下一個狀態(tài)
    if (f.mState <= newState) {
        // If we are moving to the same state, we do not need to give up on the animation.
        if (f.mState < newState && !mExitAnimationCancellationSignals.isEmpty()) {
            // The fragment is currently being animated...  but!  Now we
            // want to move our state back up.  Give up on waiting for the
            // animation and proceed from where we are.
            cancelExitAnimation(f);
        }
        switch (f.mState) {
            case Fragment.INITIALIZING:
                if (newState > Fragment.INITIALIZING) {
                    if (isLoggingEnabled(Log.DEBUG)) Log.d(TAG, "moveto ATTACHED: " + f);

                    // 如果當(dāng)前Fragment有目標(biāo)Fragment,則至少需要將目標(biāo)Fragment
                    // 的生命周期設(shè)置為CREATED狀態(tài)
                    if (f.mTarget != null) {
                        if (!f.mTarget.equals(findActiveFragment(f.mTarget.mWho))) {
                            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);
                        }
                        f.mTargetWho = f.mTarget.mWho;
                        f.mTarget = null;
                    }
                    if (f.mTargetWho != null) {
                        Fragment target = findActiveFragment(f.mTargetWho);
                        if (target == null) {
                            throw new IllegalStateException("Fragment " + f
                                    + " declared target fragment " + f.mTargetWho
                                    + " that does not belong to this FragmentManager!");
                        }
                        if (target.mState < Fragment.CREATED) {
                            moveToState(target, Fragment.CREATED);
                        }
                    }
                    // 如果當(dāng)前狀態(tài)是初始化狀態(tài)涝桅,而新的狀態(tài)比初始化狀態(tài)大
                    // 則需要將當(dāng)前狀態(tài)設(shè)置為下一個狀態(tài)拜姿,即ATTACHED狀態(tài)
                    fragmentStateManager.attach(mHost, this, mParent);
                }
                // fall through
            case Fragment.ATTACHED:
                // 如果當(dāng)前狀態(tài)是ATTACHED狀態(tài)烙样,新的狀態(tài)比當(dāng)前狀態(tài)大
                // 則需要將當(dāng)前Fragment的狀態(tài)設(shè)置為下一個狀態(tài)CREATED
                if (newState > Fragment.ATTACHED) {
                    fragmentStateManager.create();
                }
                // fall through
            case Fragment.CREATED:
                // We want to unconditionally run this anytime we do a moveToState that
                // moves the Fragment above INITIALIZING, including cases such as when
                // we move from CREATED => CREATED as part of the case fall through above.
                if (newState > Fragment.INITIALIZING) {
                    fragmentStateManager.ensureInflatedView();
                }

                if (newState > Fragment.CREATED) {
                    // 創(chuàng)建Fragment對應(yīng)的View
                    // mContainer其實就是HostCallbacks冯遂,在FragmentActivity
                    // 的onCreate方法中調(diào)用FragmentController.attachHost
                    // 方法的時候,會將HostCallbacks對象傳給FragmentController
                    fragmentStateManager.createView(mContainer);
                    fragmentStateManager.activityCreated();
                    fragmentStateManager.restoreViewState();
                }
                // fall through
            case Fragment.ACTIVITY_CREATED:
                if (newState > Fragment.ACTIVITY_CREATED) {
                    fragmentStateManager.start();
                }
                // fall through
            case Fragment.STARTED:
                if (newState > Fragment.STARTED) {
                    fragmentStateManager.resume();
                }
        }
    } else if (f.mState > newState) {
        // 如果當(dāng)前Fragment的狀態(tài)大于新的狀態(tài)
        // 說明當(dāng)前Fragment已經(jīng)要開始執(zhí)行onPause谒获、onStop等生命周期
        // 所以當(dāng)前Fragment的狀態(tài)就需要逆序依次減小
        // 比如在onPause的時候蛤肌,狀態(tài)就從RESUMED變成STARTED
        // 在onStop的時候,狀態(tài)就從STARTED變成ACTIVITY_CREATED
        switch (f.mState) {
            case Fragment.RESUMED:
                if (newState < Fragment.RESUMED) {
                    fragmentStateManager.pause();
                }
                // fall through
            case Fragment.STARTED:
                if (newState < Fragment.STARTED) {
                    fragmentStateManager.stop();
                }
                // fall through
            case Fragment.ACTIVITY_CREATED:
                // Fragment要回調(diào)onDestroyViews的時候
                // 其實是處于ACTIVITY_CREATED這個狀態(tài)
                if (newState < Fragment.ACTIVITY_CREATED) {
                    if (isLoggingEnabled(Log.DEBUG)) {
                        Log.d(TAG, "movefrom ACTIVITY_CREATED: " + f);
                    }
                    if (f.mView != null) {
                        // Need to save the current view state if not
                        // done already.
                        if (mHost.onShouldSaveFragmentState(f) && f.mSavedViewState == null) {
                            fragmentStateManager.saveViewState();
                        }
                    }
                    FragmentAnim.AnimationOrAnimator anim = null;
                    if (f.mView != null && f.mContainer != null) {
                        // Stop any current animations:
                        f.mContainer.endViewTransition(f.mView);
                        f.mView.clearAnimation();
                        // If parent is being removed, no need to handle child animations.
                        if (!f.isRemovingParent()) {
                            if (mCurState > Fragment.INITIALIZING && !mDestroyed
                                    && f.mView.getVisibility() == View.VISIBLE
                                    && f.mPostponedAlpha >= 0) {
                                anim = FragmentAnim.loadAnimation(mHost.getContext(),
                                        mContainer, f, false);
                            }
                            f.mPostponedAlpha = 0;
                            // Robolectric tests do not post the animation like a real device
                            // so we should keep up with the container and view in case the
                            // fragment view is destroyed before we can remove it.
                            ViewGroup container = f.mContainer;
                            View view = f.mView;
                            if (anim != null) {
                                f.setStateAfterAnimating(newState);
                                FragmentAnim.animateRemoveFragment(f, anim,
                                        mFragmentTransitionCallback);
                            }
                            container.removeView(view);
                            // If the local container is different from the fragment
                            // container, that means onAnimationEnd was called, onDestroyView
                            // was dispatched and the fragment was already moved to state, so
                            // we should early return here instead of attempting to move to
                            // state again.
                            if (container != f.mContainer) {
                                return;
                            }
                        }
                    }
                    // If a fragment has an exit animation (or transition), do not destroy
                    // its view immediately and set the state after animating
                    if (mExitAnimationCancellationSignals.get(f) == null) {
                        destroyFragmentView(f);
                    } else {
                        f.setStateAfterAnimating(newState);
                    }
                }
                // fall through
            case Fragment.CREATED:
                if (newState < Fragment.CREATED) {
                    boolean beingRemoved = f.mRemoving && !f.isInBackStack();
                    if (beingRemoved || mNonConfig.shouldDestroy(f)) {
                        makeInactive(fragmentStateManager);
                    } else {
                        if (f.mTargetWho != null) {
                            Fragment target = findActiveFragment(f.mTargetWho);
                            if (target != null && target.getRetainInstance()) {
                                // Only keep references to other retained Fragments
                                // to avoid developers accessing Fragments that
                                // are never coming back
                                f.mTarget = target;
                            }
                        }
                    }
                    if (mExitAnimationCancellationSignals.get(f) != null) {
                        // We are waiting for the fragment's view to finish
                        // animating away.  Just make a note of the state
                        // the fragment now should move to once the animation
                        // is done.
                        // Shared elements require that we wait on multiple Fragments, so if
                        // any of them are animating we will continue to wait.
                        f.setStateAfterAnimating(newState);
                        newState = Fragment.CREATED;
                    } else {
                        fragmentStateManager.destroy(mHost, mNonConfig);
                    }
                }
                // fall through
            case Fragment.ATTACHED:
                if (newState < Fragment.ATTACHED) {
                    fragmentStateManager.detach(mNonConfig);
                }
        }
    }

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

13.FragmentManager#execPendingActions

在針對Fragment的狀態(tài)修改執(zhí)行完成之后,繼續(xù)分析第八步中調(diào)用的execPendingActions方法。
execPendingActions方法只能是在主線程中執(zhí)行副硅,如果是在異步線程中棠隐,則會拋出異常。"Must be called from main thread of fragment host"
本方法其實就是執(zhí)行對應(yīng)的事務(wù)玫氢,scheduleCommit方法中會執(zhí)行Runnable對象mExecCommit俯艰,在mExecCommit的run方法中調(diào)用了execPendingActions方法号枕,進(jìn)行具體事務(wù)的提交权悟。scheduleCommit是在enqueueAction調(diào)用砸王,而enqueueAction是在事務(wù)對象BackStackRecord中的commit方法由commitInternal調(diào)用的。

boolean execPendingActions(boolean allowStateLoss) {
    // 確保執(zhí)行是處于就緒階段峦阁,即沒有正在執(zhí)行的事務(wù)谦铃,也HostCallbacks也不為null
    // 且是在主線程中
    ensureExecReady(allowStateLoss);

    boolean didSomething = false;
    // 這里的操作,其實就是在mPendingActions中取出BackStackRecord
    // mPendingActions中存的是OpGenerator榔昔,而BackStackRecord實現(xiàn)了該接口
    // mTmpRecords存的就是BackStackRecord
    // 所以這里的目的就算將待執(zhí)行的事務(wù)添加到mTmpRecords
    // 而在mTmpIsPop對應(yīng)位置會根據(jù)是否允許添加到回退棧而設(shè)置true還是false
    // 這里如果mPendingActions為null驹闰,則直接返回false
    while (generateOpsForPendingActions(mTmpRecords, mTmpIsPop)) {
        mExecutingActions = true;
        try {
            // 這里是刪除冗余操作,并且執(zhí)行事務(wù)
            // 所謂的冗余操作:比如一次事務(wù)提交撒会,對一個Fragment進(jìn)行了add
            // 又進(jìn)行了remove嘹朗,然后又進(jìn)行了add,這樣只有最后一次add有效
            // 在這里會修改事務(wù)的狀態(tài)茧彤,比如將replace的事務(wù)變成ADD的
            // 最終就會執(zhí)行處理事務(wù)
            // 如果沒有回退棧相關(guān)骡显,則是調(diào)用事務(wù)BackStackRecord.executeOps方法
            removeRedundantOperationsAndExecute(mTmpRecords, mTmpIsPop);
        } finally {
            cleanupExec();
        }
        didSomething = true;
    }

    updateOnBackPressedCallbackEnabled();
    // 執(zhí)行延遲啟動的Fragment,修改其狀態(tài)
    doPendingDeferredStart();
    // 這里為了防止列表錯誤曾掂,將mActive的值置為null
    // 而不是在Fragment變?yōu)榉腔顒訝顟B(tài)的時候?qū)⑵鋭h除惫谤。
    // 但是在執(zhí)行事務(wù)結(jié)束時會清理列表
    mFragmentStore.burpActive();

    return didSomething;
}

14.FragmentManager#removeRedundantOperationsAndExecute

這里的主要目的就是為了移除事務(wù)提交過程中,事務(wù)列表中冗余的BackStackRecord對象珠洗。

private void removeRedundantOperationsAndExecute(@NonNull ArrayList<BackStackRecord> records,
        @NonNull ArrayList<Boolean> isRecordPop) {
    if (records.isEmpty()) {
        return;
    }

    if (records.size() != isRecordPop.size()) {
        throw new IllegalStateException("Internal error with the back stack records");
    }

    // 針對與計劃處理的事務(wù)有交互的任何延遲的事務(wù)溜歪,進(jìn)行強制執(zhí)行
    // 不過這些事務(wù)是過去延遲處理,但是當(dāng)前已經(jīng)準(zhǔn)備好的事務(wù)
    executePostponedTransaction(records, isRecordPop);

    final int numRecords = records.size();
    int startIndex = 0;
    for (int recordNum = 0; recordNum < numRecords; recordNum++) {
        final boolean canReorder = records.get(recordNum).mReorderingAllowed;
        if (!canReorder) {
            // 執(zhí)行先前的所有事務(wù)
            if (startIndex != recordNum) {
                executeOpsTogether(records, isRecordPop, startIndex, recordNum);
            }
            // 執(zhí)行所有不允許重新排序的出棧操作或者事務(wù)的添加操作
            int reorderingEnd = recordNum + 1;
            if (isRecordPop.get(recordNum)) {
                while (reorderingEnd < numRecords
                        && isRecordPop.get(reorderingEnd)
                        && !records.get(reorderingEnd).mReorderingAllowed) {
                    reorderingEnd++;
                }
            }
            executeOpsTogether(records, isRecordPop, recordNum, reorderingEnd);
            startIndex = reorderingEnd;
            recordNum = reorderingEnd - 1;
        }
    }
    if (startIndex != numRecords) {
        executeOpsTogether(records, isRecordPop, startIndex, numRecords);
    }
}

15.FragmentManager#executeOpsTogether

private void executeOpsTogether(@NonNull ArrayList<BackStackRecord> records,
        @NonNull ArrayList<Boolean> isRecordPop, int startIndex, int endIndex) {
    final boolean allowReordering = records.get(startIndex).mReorderingAllowed;
    boolean addToBackStack = false;
    if (mTmpAddedFragments == null) {
        mTmpAddedFragments = new ArrayList<>();
    } else {
        mTmpAddedFragments.clear();
    }
    mTmpAddedFragments.addAll(mFragmentStore.getFragments());
    Fragment oldPrimaryNav = getPrimaryNavigationFragment();
    for (int recordNum = startIndex; recordNum < endIndex; recordNum++) {
        final BackStackRecord record = records.get(recordNum);
        final boolean isPop = isRecordPop.get(recordNum);
        if (!isPop) {
            // 如果是不允許出棧的许蓖,修改事務(wù)的操作狀態(tài)
            // 比如將replace的操作也變成了ADD操作
            oldPrimaryNav = record.expandOps(mTmpAddedFragments, oldPrimaryNav);
        } else {
            oldPrimaryNav = record.trackAddedFragmentsInPop(mTmpAddedFragments, oldPrimaryNav);
        }
        addToBackStack = addToBackStack || record.mAddToBackStack;
    }
    mTmpAddedFragments.clear();

    if (!allowReordering) {
        FragmentTransition.startTransitions(this, records, isRecordPop, startIndex, endIndex,
                false, mFragmentTransitionCallback);
    }
    // 這里是具體執(zhí)行對Fragment的add蝴猪、replace、hide膊爪、show等操作的
    executeOps(records, isRecordPop, startIndex, endIndex);

    int postponeIndex = endIndex;
    if (allowReordering) {
        ArraySet<Fragment> addedFragments = new ArraySet<>();
        addAddedFragments(addedFragments);
        postponeIndex = postponePostponableTransactions(records, isRecordPop,
                startIndex, endIndex, addedFragments);
        makeRemovedFragmentsInvisible(addedFragments);
    }

    if (postponeIndex != startIndex && allowReordering) {
        // need to run something now
        FragmentTransition.startTransitions(this, records, isRecordPop, startIndex,
                postponeIndex, true, mFragmentTransitionCallback);
        moveToState(mCurState, true);
    }

    for (int recordNum = startIndex; recordNum < endIndex; recordNum++) {
        final BackStackRecord record = records.get(recordNum);
        final boolean isPop = isRecordPop.get(recordNum);
        if (isPop && record.mIndex >= 0) {
            record.mIndex = -1;
        }
        record.runOnCommitRunnables();
    }
    if (addToBackStack) {
        reportBackStackChanged();
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末自阱,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子米酬,更是在濱河造成了極大的恐慌沛豌,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,386評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件赃额,死亡現(xiàn)場離奇詭異加派,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)跳芳,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評論 3 394
  • 文/潘曉璐 我一進(jìn)店門芍锦,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人飞盆,你說我怎么就攤上這事娄琉〈闻遥” “怎么了?”我有些...
    開封第一講書人閱讀 164,704評論 0 353
  • 文/不壞的土叔 我叫張陵孽水,是天一觀的道長檬输。 經(jīng)常有香客問我,道長匈棘,這世上最難降的妖魔是什么丧慈? 我笑而不...
    開封第一講書人閱讀 58,702評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮主卫,結(jié)果婚禮上逃默,老公的妹妹穿的比我還像新娘。我一直安慰自己簇搅,他們只是感情好完域,可當(dāng)我...
    茶點故事閱讀 67,716評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著瘩将,像睡著了一般吟税。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上姿现,一...
    開封第一講書人閱讀 51,573評論 1 305
  • 那天肠仪,我揣著相機(jī)與錄音,去河邊找鬼备典。 笑死异旧,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的提佣。 我是一名探鬼主播吮蛹,決...
    沈念sama閱讀 40,314評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼拌屏!你這毒婦竟也來了潮针?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,230評論 0 276
  • 序言:老撾萬榮一對情侶失蹤倚喂,失蹤者是張志新(化名)和其女友劉穎每篷,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體务唐,經(jīng)...
    沈念sama閱讀 45,680評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡雳攘,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,873評論 3 336
  • 正文 我和宋清朗相戀三年带兜,在試婚紗的時候發(fā)現(xiàn)自己被綠了枫笛。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,991評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡刚照,死狀恐怖刑巧,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤啊楚,帶...
    沈念sama閱讀 35,706評論 5 346
  • 正文 年R本政府宣布吠冤,位于F島的核電站,受9級特大地震影響恭理,放射性物質(zhì)發(fā)生泄漏拯辙。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,329評論 3 330
  • 文/蒙蒙 一颜价、第九天 我趴在偏房一處隱蔽的房頂上張望涯保。 院中可真熱鬧,春花似錦周伦、人聲如沸夕春。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,910評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽及志。三九已至,卻和暖如春寨腔,著一層夾襖步出監(jiān)牢的瞬間速侈,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,038評論 1 270
  • 我被黑心中介騙來泰國打工迫卢, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留锌畸,地道東北人。 一個月前我還...
    沈念sama閱讀 48,158評論 3 370
  • 正文 我出身青樓靖避,卻偏偏與公主長得像潭枣,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子幻捏,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,941評論 2 355

推薦閱讀更多精彩內(nèi)容