AndroidX Fragment探究-事務操作

概述

平時開發中經常使用Fragment的場景是創建Fragment並添加到FragmentActivity的指定佈局容器中。要實現這樣的操作,首先需要獲取FragmentManager,接着開啓事務FragmentTransaction,並添加add、remove、replace、hide、show等等操作,最後commitXXX提交事務執行對應操作。

接下來進入源碼追蹤這個過程,看看FragmentManager是如何進行調度執行。

源碼探究

文中源碼基於’androidx.fragment:fragment:1.1.0’

FragmentManager的由來

在FragmentActivity中通過getSupportFragmentManager方法來獲取FragmentManager:

[FragmentActivity.java]

public FragmentManager getSupportFragmentManager() {
    return mFragments.getSupportFragmentManager();
}

該方法中又通過mFragments成員來獲取:
[FragmentController.java]

public FragmentManager getSupportFragmentManager() {
    return mHost.mFragmentManager;
}

其中又通過mHost成員來獲取。

在研究FragmentManager之前,先來看看mFragments、mHost是什麼。

FragmentController

先來看看FragmentActivity的mFragments成員:

[FragmentActivity.java]

public class FragmentActivity extends ComponentActivity implements
        ActivityCompat.OnRequestPermissionsResultCallback,
        ActivityCompat.RequestPermissionsRequestCodeValidator {
    // ···
    final FragmentController mFragments = FragmentController.createController(new HostCallbacks());
    // ···
}

mFragments爲FragmentController對象。

接着看createController方法,這裏傳入HostCallbacks實例:
[FragmentController.java]

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

private FragmentController(FragmentHostCallback<?> callbacks) {
    // 持有HostCallbacks引用
    mHost = callbacks;
}

HostCallbacks

在創建FragmentController時,實例化了HostCallbacks並賦值給FragmentController的mHost成員。

[FragmentActivity.java]

class HostCallbacks extends FragmentHostCallback<FragmentActivity> implements
        ViewModelStoreOwner,
        OnBackPressedDispatcherOwner {
    public HostCallbacks() {
        super(FragmentActivity.this /*fragmentActivity*/);
    }
    // ···
}

HostCallbacks繼承自FragmentHostCallback,爲FragmentActivity的內部類,持有FragmentActivity的引用。

[FragmentHostCallback.java]

public abstract class FragmentHostCallback<E> extends FragmentContainer {
    // ···
    FragmentHostCallback(@NonNull FragmentActivity activity) {
        this(activity, activity /*context*/, new Handler(), 0 /*windowAnimations*/);
    }

    FragmentHostCallback(@Nullable Activity activity, @NonNull Context context,
            @NonNull Handler handler, int windowAnimations) {
        // 持有FragmentActivity上下文引用
        mActivity = activity;
        mContext = Preconditions.checkNotNull(context, "context == null");
        // 構造函數中創建的Handler,默認運行在主線程
        mHandler = Preconditions.checkNotNull(handler, "handler == null");
        // 動畫相關,默認爲0
        mWindowAnimations = windowAnimations;
    }
    // ···
}

可以看出HostCallbacks持有當前FragmentActivity上下文,並創建了一個主線程Handler。

FragmentManagerImpl

FragmentManager爲抽象類,而FragmentManagerImpl是其實現類:

[FragmentManagerImpl.java]

final class FragmentManagerImpl extends FragmentManager implements LayoutInflater.Factory2 {
    // ···
}

在FragmentHostCallback實例化時會創建FragmentManagerImpl:
[FragmentHostCallback.java]

public abstract class FragmentHostCallback<E> extends FragmentContainer {
    // ···
    final FragmentManagerImpl mFragmentManager = new FragmentManagerImpl();
    // ···
}

FragmentHostCallback的mFragmentManager成員持有FragmentManagerImpl。

FragmentManagerImpl的綁定

在FragmentActivity的onCreate方法中:
[FragmentActivity.java]

protected void onCreate(@Nullable Bundle savedInstanceState) {
    // 調用FragmentController的attachHost方法,參數傳null
    mFragments.attachHost(null /*parent*/);
    // ···
}

接着看attachHost方法:
[FragmentController.java]

public void attachHost(@Nullable Fragment parent) {
    // 調用FragmentManagerImpl的attachController方法,並傳入HostCallbacks實例,參數parent爲null。
    mHost.mFragmentManager.attachController(
            mHost, mHost /*container*/, parent);
}

進入FragmentManagerImpl的attachController方法:
[FragmentManagerImpl.java]

public void attachController(@NonNull FragmentHostCallback host,
        @NonNull FragmentContainer container, @Nullable final Fragment parent) {
    if (mHost != null) throw new IllegalStateException("Already attached");
    // 持有HostCallbacks引用
    mHost = host;
    mContainer = container;
    mParent = parent;
    if (mParent != null) {
        // Since the callback depends on us being the primary navigation fragment,
        // update our callback now that we have a parent so that we have the correct
        // state by default
        updateOnBackPressedCallbackEnabled();
    }
    // Set up the OnBackPressedCallback
    // 省略BackPressed設置部分
    // ···
    
    // Get the FragmentManagerViewModel
    // 省略ViewModel設置部分
    // ···
}

FragmentActivity在onCreate中進行FragmentManagerImpl的綁定操作,在FragmentManagerImpl的attachController方法中接收HostCallbacks實例並保存。

FragmentController、HostCallbacks、FragmentManagerImpl之間關係

FragmentController類圖

FragmentActivity持有FragmentController引用,FragmentController持有HostCallbacks引用,HostCallbacks持有FragmentActivity引用,FragmentActivity和FragmentManagerImpl互相持有引用。

FragmentActivity通過FragmentController獲取HostCallbacks,再通過HostCallbacks間接調用FragmentManagerImpl。FragmentManagerImpl通過HostCallbacks來間接獲取上下文和執行回調方法。

添加事務操作

開啓事務

獲取到FragmentManagerImpl實例後,通過它的beginTransaction方法開啓一個事務:
[FragmentManagerImpl.java]

public FragmentTransaction beginTransaction() {
    return new BackStackRecord(this);
}

這裏創建BackStackRecord(繼承自FragmentTransaction,並實現BackStackEntry、OpGenerator接口),BackStackRecord將持有FragmentManagerImpl。

FragmentTransaction封裝一個事務,一個事務包含一組操作(單個或多個操作)。

添加add Fragment的操作

這裏以,往FragmentActivity中添加一個Fragment爲例。

通常添加Fragment是通過調用FragmentTransaction的add方法,傳入佈局ID和Fragment實例:
[FragmentTransaction.java]

public FragmentTransaction add(@IdRes int containerViewId, @NonNull Fragment fragment,
        @Nullable String tag) {
    // tag可選參數,可通過tag查找fragment,OP_ADD標識add操作類型
    doAddOp(containerViewId, fragment, tag, OP_ADD);
    return this;
}

BackStackRecord重寫了doAddOp方法:
[BackStackRecord.java]

void doAddOp(int containerViewId, Fragment fragment, @Nullable String tag, int opcmd) {
    super.doAddOp(containerViewId, fragment, tag, opcmd);
    // 將持有的FragmentManagerImpl賦值給Fragment的mFragmentManager成員
    fragment.mFragmentManager = mManager;
}

該方法中通過super還是調用FragmentTransaction的doAddOp,只是在執行完後爲Fragment的mFragmentManager成員賦值。

[FragmentTransaction.java]

void doAddOp(int containerViewId, Fragment fragment, @Nullable String tag, int opcmd) {
    final Class<?> fragmentClass = fragment.getClass();
    final int modifiers = fragmentClass.getModifiers();
    // 檢查fragment是否是匿名類,或者非public訪問性,或者定義在另一個類中但沒有聲明static
    if (fragmentClass.isAnonymousClass() || !Modifier.isPublic(modifiers)
            || (fragmentClass.isMemberClass() && !Modifier.isStatic(modifiers))) {
        throw new IllegalStateException("Fragment " + fragmentClass.getCanonicalName()
                + " must be a public static class to be  properly recreated from"
                + " instance state.");
    }

    if (tag != null) {
        // 檢查是否fragment已有tag但和當前傳入的tag不同
        if (fragment.mTag != null && !tag.equals(fragment.mTag)) {
            throw new IllegalStateException("Can't change tag of fragment "
                    + fragment + ": was " + fragment.mTag
                    + " now " + tag);
        }
        // fragment保存tag
        fragment.mTag = tag;
    }

    // containerViewId即爲FragmentActivity中用於添加這個fragment的佈局容器ID
    if (containerViewId != 0) {
        if (containerViewId == View.NO_ID) {
            throw new IllegalArgumentException("Can't add fragment "
                    + fragment + " with tag " + tag + " to container view with no id");
        }
        // 檢查是否fragment已經設置容器ID但與當前傳入的ID不同
        if (fragment.mFragmentId != 0 && fragment.mFragmentId != containerViewId) {
            throw new IllegalStateException("Can't change container ID of fragment "
                    + fragment + ": was " + fragment.mFragmentId
                    + " now " + containerViewId);
        }
        // fragment保存容器ID,mFragmentId默認爲容器ID
        fragment.mContainerId = fragment.mFragmentId = containerViewId;
    }
    
    // 添加操作
    addOp(new Op(opcmd, fragment));
}

該方法中做了以下幾步:

  1. 該方法中首先校驗我們自定義的Fragment:
  • 不能是匿名類
  • 訪問性必須是public
  • 若是成員類,必須是靜態類
  1. 接着檢查tag(若有傳入)是否和fragment已有保存的不同,最後保存在fragment中
  2. 接着檢查佈局ID(若有傳入),該佈局爲FragmentActivity中用於承載fragment的ViewGroup,必須有設置ID,fragment中若已有設置必須相同,最後fragment保存容器ID,mFragmentId默認也爲容器ID
  3. 封裝Op保存操作類型和fragment,並添加至操作集合
Op

Op表示一個操作,看它的構造函數:

[FragmentTransaction.java]

Op(int cmd, Fragment fragment) {
    // 保存操作類型
    this.mCmd = cmd;
    // 保存待操作的fragment
    this.mFragment = fragment;
    // 生命週期狀態置爲RESUMED,對應Activity執行onResume之後的狀態
    this.mOldMaxState = Lifecycle.State.RESUMED;
    this.mCurrentMaxState = Lifecycle.State.RESUMED;
}
addOp

[FragmentTransaction.java]

void addOp(Op op) {
    // 保存Op對象
    mOps.add(op);
    // 動畫相關,默認都爲0
    op.mEnterAnim = mEnterAnim;
    op.mExitAnim = mExitAnim;
    op.mPopEnterAnim = mPopEnterAnim;
    op.mPopExitAnim = mPopExitAnim;
}

FragmentTransaction的mOps成員用於保存Op對象,mOps爲ArrayList。

提交事務

FragmentTransaction有四個提交事務的方法:commit、commitAllowingStateLoss、commitNow、commitNowAllowingStateLoss。這四個方法都爲抽象類,具體實現在BackStackRecord中。

這裏以commitAllowingStateLoss爲例:
[BackStackRecord.java]

public int commitAllowingStateLoss() {
    return commitInternal(true);
}

int commitInternal(boolean allowStateLoss) {
    if (mCommitted) throw new IllegalStateException("commit already called");
    // 省略DEBUG部分 ···
    mCommitted = true;
    // mAddToBackStack默認爲false,若調用addToBackStack方法的話爲true
    if (mAddToBackStack) {
        mIndex = mManager.allocBackStackIndex(this);
    } else {
        mIndex = -1;
    }
    // 此時傳入的allowStateLoss爲true
    // 通過FragmentManagerImpl入隊
    mManager.enqueueAction(this, allowStateLoss);
    return mIndex;
}

接着看FragmentManagerImpl的enqueueAction方法,此時傳入BackStackRecord自身和true:
[FragmentManagerImpl.java]

public void enqueueAction(OpGenerator action, boolean allowStateLoss) {
    if (!allowStateLoss) {
        checkStateLoss();
    }
    synchronized (this) {
        if (mDestroyed || mHost == null) {
            if (allowStateLoss) {
                // This FragmentManager isn't attached, so drop the entire transaction.
                return;
            }
            throw new IllegalStateException("Activity has been destroyed");
        }
        if (mPendingActions == null) {
            mPendingActions = new ArrayList<>();
        }
        // mPendingActions表示待執行操作集合,action即爲BackStackRecord(實現了OpGenerator接口)
        mPendingActions.add(action);
        scheduleCommit();
    }
}

接着看scheduleCommit方法:
[FragmentManagerImpl.java]

void scheduleCommit() {
    synchronized (this) {
        // 標記是否存在延遲事務,默認不存在
        boolean postponeReady =
                mPostponedTransactions != null && !mPostponedTransactions.isEmpty();
        // 標記是否僅存在一個待執行事務,第一次通過enqueueAction提交事務時符合條件
        boolean pendingReady = mPendingActions != null && mPendingActions.size() == 1;
        if (postponeReady || pendingReady) {
            // 符合條件,通過Handler調度任務執行
            mHost.getHandler().removeCallbacks(mExecCommit);
            mHost.getHandler().post(mExecCommit);
            updateOnBackPressedCallbackEnabled();
        }
    }
}

當存在延遲事務或第一次提交事務時,會通過Handler來post一個Runnable執行操作,這裏的Handler即HostCallbacks實例化時創建的主線程Handler。

可見通過commit、commitAllowingStateLoss方法提交的事務不會立即執行,而是等待主線程LOOPER下一次取出消息時執行。

處理事務操作

前文中使用Handler post的mExecCommit是一個Runnable:
[FragmentManagerImpl.java]

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

觸發時將調用execPendingActions方法處理事務操作:
[FragmentManagerImpl.java]

public boolean execPendingActions() {
    // 檢查狀態和初始化mTmpRecords、mTmpIsPop集合和處理延遲事務
    ensureExecReady(true);

    boolean didSomething = false;
    // 生成命令並保存在mTmpRecords、mTmpIsPop集合中
    while (generateOpsForPendingActions(mTmpRecords, mTmpIsPop)) {
        // 標記當前處於執行事務中
        mExecutingActions = true;
        try {
            // 移除或合併多餘的操作並執行
            removeRedundantOperationsAndExecute(mTmpRecords, mTmpIsPop);
        } finally {
            cleanupExec();
        }
        didSomething = true;
    }

    updateOnBackPressedCallbackEnabled();
    // 執行推遲啓動的Fragment
    doPendingDeferredStart();
    // 清理mActive集合
    burpActive();

    return didSomething;
}

該方法中會在一個while循環中檢索待執行事務並執行,當generateOpsForPendingActions返回false表示沒有待執行的事務,則結束while循環。

兩個集合的說明:

  • mTmpRecords:保存待執行的BackStackRecord。
  • mTmpIsPop:標記與mTmpRecords對應索引的BackStackRecord是添加類型還是移除類型的,默認爲false,通過popBackStack回退時,會標記對應索引位置爲true。

generateOpsForPendingActions

[FragmentManagerImpl.java]

private boolean generateOpsForPendingActions(ArrayList<BackStackRecord> records,
                                             ArrayList<Boolean> isPop) {
    // 標記是否有執行事務
    boolean didSomething = false;
    synchronized (this) {
        // 若不存在待執行事務則返回false
        if (mPendingActions == null || mPendingActions.size() == 0) {
            return false;
        }

        final int numActions = mPendingActions.size();
        // 遍歷mPendingActions,此時僅有一個OP_ADD類型的BackStackRecord
        for (int i = 0; i < numActions; i++) {
            // 依次調用generateOps方法
            didSomething |= mPendingActions.get(i).generateOps(records, isPop);
        }
        // 清空mPendingActions
        mPendingActions.clear();
        // 移除mExecCommit,避免冗餘執行
        mHost.getHandler().removeCallbacks(mExecCommit);
    }
    return didSomething;
}

generateOps

這裏以添加Fragment爲例,此時mPendingActions中存在一個OP_ADD類型的BackStackRecord,查看它的generateOps方法:
[BackStackRecord.java]

public boolean generateOps(ArrayList<BackStackRecord> records, ArrayList<Boolean> isRecordPop) {
    if (FragmentManagerImpl.DEBUG) {
        Log.v(TAG, "Run: " + this);
    }

    // records集合添加BackStackRecord自身
    records.add(this);
    // isRecordPop添加false
    isRecordPop.add(false);
    // mAddToBackStack默認爲false,因此不加入回退棧
    if (mAddToBackStack) {
        mManager.addBackStackState(this);
    }
    return true;
}

removeRedundantOperationsAndExecute

[FragmentManagerImpl.java]

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

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

    // Force start of any postponed transactions that interact with scheduled transactions:
    executePostponedTransaction(records, isRecordPop);

    final int numRecords = records.size();
    int startIndex = 0;
    for (int recordNum = 0; recordNum < numRecords; recordNum++) {
        // 標記是否支持操作排序優化,默認爲false
        final boolean canReorder = records.get(recordNum).mReorderingAllowed;
        if (!canReorder) {
            // execute all previous transactions
            if (startIndex != recordNum) {
                executeOpsTogether(records, isRecordPop, startIndex, recordNum);
            }
            // execute all pop operations that don't allow reordering together or
            // one add operation
            int reorderingEnd = recordNum + 1;
            // 非pop事務都返回false
            if (isRecordPop.get(recordNum)) {
                while (reorderingEnd < numRecords
                        && isRecordPop.get(reorderingEnd)
                        && !records.get(reorderingEnd).mReorderingAllowed) {
                    reorderingEnd++;
                }
            }
            // 執行指定索引區間中的BackStackRecord
            executeOpsTogether(records, isRecordPop, recordNum, reorderingEnd);
            startIndex = reorderingEnd;
            recordNum = reorderingEnd - 1;
        }
    }
    if (startIndex != numRecords) {
        // 開啓操作排序優化情況下可能會滿足該if條件
        executeOpsTogether(records, isRecordPop, startIndex, numRecords);
    }
}
操作排序優化

當有多個待執行事務時,FragmentManager會刪除部分冗餘事務操作。例如:

  • 假設有兩個事務對同一佈局容器一起執行,一個事務添加了一個 Fragment A,下一個事務將其替換爲 Fragment B。則優化後會將第一個操作取消,僅添加 Fragment B。
  • 假設有三個事務,一個事務添加了 Fragment A,第二個事務添加了 Fragment B,然後第三個刪除了 Fragment A。那麼優化後將不會執行 Fragment A的添加和刪除,僅添加 Fragment B。

排序優化操作會導致出現超出開發者預期的行爲,因此默認不進行此操作。

executeOpsTogether

進入executeOpsTogether方法:
[FragmentManagerImpl.java]

private void executeOpsTogether(ArrayList<BackStackRecord> records,
                                ArrayList<Boolean> isRecordPop, int startIndex, int endIndex) {
    // ···
    executeOps(records, isRecordPop, startIndex, endIndex);
    // ···
}

進入executeOps方法:
[FragmentManagerImpl.java]

private static void executeOps(ArrayList<BackStackRecord> records,
                               ArrayList<Boolean> isRecordPop, int startIndex, int endIndex) {
    for (int i = startIndex; i < endIndex; i++) {
        final BackStackRecord record = records.get(i);
        final boolean isPop = isRecordPop.get(i);
        if (isPop) {
            record.bumpBackStackNesting(-1);
            // Only execute the add operations at the end of
            // all transactions.
            boolean moveToState = i == (endIndex - 1);
            // 執行回退操作
            record.executePopOps(moveToState);
        } else {
            record.bumpBackStackNesting(1);
            // OP_ADD類型執行executeOps
            record.executeOps();
        }
    }
}

executeOps

看BackStackRecord的executeOps方法中的OP_ADD case:
[BackStackRecord.java]

void executeOps() {
    final int numOps = mOps.size();
    // 遍歷該事務中的操作
    for (int opNum = 0; opNum < numOps; opNum++) {
        final Op op = mOps.get(opNum);
        final Fragment f = op.mFragment;
        if (f != null) {
            f.setNextTransition(mTransition, mTransitionStyle);
        }
        switch (op.mCmd) {
            case OP_ADD:
                f.setNextAnim(op.mEnterAnim);
                // 添加Fragment
                mManager.addFragment(f, false);
                break;
            // 省略其他case ···
            default:
                throw new IllegalArgumentException("Unknown cmd: " + op.mCmd);
        }
        if (!mReorderingAllowed && op.mCmd != OP_ADD && f != null) {
            mManager.moveFragmentToExpectedState(f);
        }
    }
    // mReorderingAllowed默認爲false
    if (!mReorderingAllowed) {
        // Added fragments are added at the end to comply with prior behavior.
        // 更新狀態,這裏傳入FragmentManagerImpl的當前狀態和true
        mManager.moveToState(mManager.mCurState, true);
    }
}

該方法中處理OP_ADD時,首先通過addFragment方法添加fragment至集合中保存,最後通過moveToState更新狀態並設置fragment。

addFragment

[FragmentManagerImpl.java]

public void addFragment(Fragment fragment, boolean moveToStateNow) {
    if (DEBUG) Log.v(TAG, "add: " + fragment);
    // 將fragment添加至mActive集合保存,若設置setRetainInstance還將添加入FragmentManagerViewModel中保存
    makeActive(fragment);
    // 此時爲OP_ADD操作,mDetached爲false
    if (!fragment.mDetached) {
        if (mAdded.contains(fragment)) {
            throw new IllegalStateException("Fragment already added: " + fragment);
        }
        synchronized (mAdded) {
            // fragment加入mAdded集合
            mAdded.add(fragment);
        }
        // mAdded用於標記該fragment是否已經加入mAdded集合
        fragment.mAdded = true;
        // mRemoving標記該fragment是否從Activity移除
        fragment.mRemoving = false;
        // 此時mView還未生成,爲null
        if (fragment.mView == null) {
            fragment.mHiddenChanged = false;
        }
        if (isMenuAvailable(fragment)) {
            mNeedMenuInvalidate = true;
        }
        // 此時傳入的moveToStateNow爲false
        if (moveToStateNow) {
            moveToState(fragment);
        }
    }
}

將fragment添加入mActive和mAdded集合中。

moveToState

回到BackStackRecord.executeOps方法中,在方法的最後執行moveToState方法:

[FragmentManagerImpl.java]

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

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

    // 更新狀態,此時傳入的newState和mCurState相等
    mCurState = newState;

    // Must add them in the proper order. mActive fragments may be out of order
    final int numAdded = mAdded.size();
    // 遍歷mAdded,依次取出Fragment處理
    for (int i = 0; i < numAdded; i++) {
        Fragment f = mAdded.get(i);
        moveFragmentToExpectedState(f);
    }

    // 省略···
}

該方法中依次取出Fragment,調用moveFragmentToExpectedState將Fragment根據最終期望的狀態進行初始化設置。

mCurState成員記錄FragmentManagerImpl的當前狀態,狀態值有:

  • INITIALIZING(0):初始狀態,默認狀態
  • CREATED(1):初創狀態,對應onCreate、onDestroyView階段
  • ACTIVITY_CREATED(2):created以上、started未滿狀態,對應onStart、onStop階段
  • STARTED(3):started以上、resumed未滿階段,對應onResume、onPause階段
  • RESUMED(4):resumed以上狀態,對應onResume完成階段

看moveFragmentToExpectedState方法:
[FragmentManagerImpl.java]

void moveFragmentToExpectedState(Fragment f) {
    if (f == null) {
        return;
    }
    if (!mActive.containsKey(f.mWho)) {
        if (DEBUG) {
            Log.v(TAG, "Ignoring moving " + f + " to state " + mCurState
                    + "since it is not added to " + this);
        }
        return;
    }
    int nextState = mCurState;
    if (f.mRemoving) {
        if (f.isInBackStack()) {
            nextState = Math.min(nextState, Fragment.CREATED);
        } else {
            nextState = Math.min(nextState, Fragment.INITIALIZING);
        }
    }
    // 調度fragment到目標狀態對應階段,並執行對應階段的初始化設置
    moveToState(f, nextState, f.getNextTransition(), f.getNextTransitionStyle(), false);

    if (f.mView != null) {
        // ···
    }
    if (f.mHiddenChanged) {
        completeShowHideFragment(f);
    }
}

該方法中調用另一個moveToState重載方法:
[FragmentManagerImpl.java]

void moveToState(Fragment f, int newState, int transit, int transitionStyle,
                 boolean keepActive) {
    // 省略狀態檢查校驗部分
    // ···
    
    // 判斷fragment的生命週期狀態是否小等於FragmentManager的狀態,剛創建添加的fragment狀態默認爲INITIALIZING
    if (f.mState <= newState) {
        // ···
        switch (f.mState) {
            case Fragment.INITIALIZING:
                // 開始進入attach階段
                if (newState > Fragment.INITIALIZING) {
                    if (DEBUG) Log.v(TAG, "moveto CREATED: " + f);
                    // 省略mSavedFragmentState部分 ···

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

                    // 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.
                    // 省略mTarget部分 ···
                    // 省略mTargetWho部分 ···

                    dispatchOnFragmentPreAttached(f, mHost.getContext(), false);
                    f.performAttach();
                    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;
                    }
                }
                // fall through
                // 注意此處無break,會繼續往下匹配case執行
            case Fragment.CREATED:
                // 開始進入CreateView階段
                // 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) {
                    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"));
                            }
                            // 獲取佈局容器,通過FragmentActivity.this.findViewById(f.mContainerId)獲取
                            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));
                            }
                        }
                        f.mContainer = container;
                        // performGetLayoutInflater中通過FragmentActivity上下文獲取LayoutInflater
                        // performCreateView中會觸發fragment的onCreateView方法,
                        // 返回我們自定義的視圖,並賦值給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) {
                                // 將fragment的view加入佈局容器中
                                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) {
                    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) {
        // 省略生命週期逆生長部分,即onPause、onStop、onDestroyView、onDestroy、onDetach
        // ···
    }
    
    if (f.mState != newState) {
        Log.w(TAG, "moveToState: Fragment state for " + f + " not updated inline; "
                + "expected state " + newState + " found " + f.mState);
        // 更新fragment的狀態
        f.mState = newState;
    }
}

moveToState方法中在CREATED狀態階段,完成了Fragment視圖的創建(若有自定義視圖),接着添加至給定的佈局容器中。

moveToState方法還會根據Fragment和FragmentManager當前的生命週期狀態,調度Fragment的狀態更新,在其中還會觸發Fragment各階段的生命週期回調方法。

REMOVE操作類型

通過調用BackStackRecord的remove方法,傳入指定Fragment,達到移除Fragment的作用。

[BackStackRecord.java]

public FragmentTransaction remove(@NonNull Fragment fragment) {
    if (fragment.mFragmentManager != null && fragment.mFragmentManager != mManager) {
        throw new IllegalStateException("Cannot remove Fragment attached to "
                + "a different FragmentManager. Fragment " + fragment.toString() + " is already"
                + " attached to a FragmentManager.");
    }
    return super.remove(fragment);
}

調用父類FragmentTransaction的remove方法:
[FragmentTransaction.java]

public FragmentTransaction remove(@NonNull Fragment fragment) {
    addOp(new Op(OP_REMOVE, fragment));

    return this;
}

remove方法中創建Op對象,傳入命令類型OP_REMOVE和要移除的fragment,添加到命令集合mOps成員中。

接下來的步驟就是提交事務,加入事務隊列,等待調度執行,同OP_ADD一樣,將會執行BackStackRecord的executeOps方法:
[BackStackRecord.java]

void executeOps() {
    for (int opNum = 0; opNum < numOps; opNum++) {
        final Op op = mOps.get(opNum);
        final Fragment f = op.mFragment;
        if (f != null) {
            f.setNextTransition(mTransition, mTransitionStyle);
        }
        switch (op.mCmd) {
            // ···
            case OP_REMOVE:
                f.setNextAnim(op.mExitAnim);
                // 將該fragment從FragmentManagerImpl的mAdded成員中移除,並設置
                // 該fragment的mAdded成員爲false、mRemoving成員爲true
                mManager.removeFragment(f);
                break;
            // ···
        }
        // mReorderingAllowed默認爲false
        if (!mReorderingAllowed && op.mCmd != OP_ADD && f != null) {
            // 更新fragment的生命狀態和執行對應階段的生命週期回調和釋放銷燬
            mManager.moveFragmentToExpectedState(f);
        }
    }
    if (!mReorderingAllowed) {
        // Added fragments are added at the end to comply with prior behavior.
        // 更新當前FragmentManagerImpl中管理的Fragment的狀態
        mManager.moveToState(mManager.mCurState, true);
    }
}

moveFragmentToExpectedState和moveToState方法在處理OP_ADD命令時見到過,是通用方法,其他命令也都會調用這兩個方法。

[FragmentManagerImpl.java]

void moveFragmentToExpectedState(Fragment f) {
    // ···
    int nextState = mCurState;
    // mRemoving此時已經置爲true
    if (f.mRemoving) {
        // 修改要更新至的目標狀態,若該fragment不爲最後一個,則目標狀態爲CREATED
        if (f.isInBackStack()) {
            nextState = Math.min(nextState, Fragment.CREATED);
        } else {
            nextState = Math.min(nextState, Fragment.INITIALIZING);
        }
    }
    // 調度fragment到目標狀態對應階段,並執行對應階段的處理
    moveToState(f, nextState, f.getNextTransition(), f.getNextTransitionStyle(), false);
    // ···
}

[FragmentManagerImpl.java]

void moveToState(Fragment f, int newState, int transit, int transitionStyle,
                 boolean keepActive) {
    // ···
    if (f.mState <= newState) {
        // ···
    } else if (f.mState > newState) {
        switch (f.mState) {
            case Fragment.RESUMED:
                // ···
            case Fragment.STARTED:
                // ···
            case Fragment.ACTIVITY_CREATED:
                if (newState < Fragment.ACTIVITY_CREATED) {
                    if (DEBUG) Log.v(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) {
                            saveFragmentViewState(f);
                        }
                    }
                    f.performDestroyView();
                    dispatchOnFragmentViewDestroyed(f, false);
                    if (f.mView != null && f.mContainer != null) {
                        // Stop any current animations:
                        f.mContainer.endViewTransition(f.mView);
                        f.mView.clearAnimation();
                        AnimationOrAnimator anim = null;
                        // If parent is being removed, no need to handle child animations.
                        if (f.getParentFragment() == null || !f.getParentFragment().mRemoving) {
                            if (mCurState > Fragment.INITIALIZING && !mDestroyed
                                    && f.mView.getVisibility() == View.VISIBLE
                                    && f.mPostponedAlpha >= 0) {
                                anim = loadAnimation(f, transit, false,
                                        transitionStyle);
                            }
                            f.mPostponedAlpha = 0;
                            if (anim != null) {
                                animateRemoveFragment(f, anim, newState);
                            }
                            // 設置了view和佈局容器的情況下,需要從佈局中移除該Fragment的view
                            f.mContainer.removeView(f.mView);
                        }
                    }
                    // 解除引用
                    f.mContainer = null;
                    f.mView = null;
                    // Set here to ensure that Observers are called after
                    // the Fragment's view is set to null
                    f.mViewLifecycleOwner = null;
                    f.mViewLifecycleOwnerLiveData.setValue(null);
                    f.mInnerView = null;
                    f.mInLayout = false;
                }
                // fall through
            case Fragment.CREATED:
                if (newState < Fragment.CREATED) {
                    if (mDestroyed) {
                        // The fragment's containing activity is
                        // being destroyed, but this fragment is
                        // currently animating away.  Stop the
                        // animation right now -- it is not needed,
                        // and we can't wait any more on destroying
                        // the fragment.
                        if (f.getAnimatingAway() != null) {
                            View v = f.getAnimatingAway();
                            f.setAnimatingAway(null);
                            v.clearAnimation();
                        } else if (f.getAnimator() != null) {
                            Animator animator = f.getAnimator();
                            f.setAnimator(null);
                            animator.cancel();
                        }
                    }
                    if (f.getAnimatingAway() != null || f.getAnimator() != 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.
                        f.setStateAfterAnimating(newState);
                        newState = Fragment.CREATED;
                    } else {
                        if (DEBUG) Log.v(TAG, "movefrom CREATED: " + f);
                        boolean beingRemoved = f.mRemoving && !f.isInBackStack();
                        if (beingRemoved || mNonConfig.shouldDestroy(f)) {
                            boolean shouldClear;
                            if (mHost instanceof ViewModelStoreOwner) {
                                shouldClear = mNonConfig.isCleared();
                            } else if (mHost.getContext() instanceof Activity) {
                                Activity activity = (Activity) mHost.getContext();
                                shouldClear = !activity.isChangingConfigurations();
                            } else {
                                shouldClear = true;
                            }
                            if (beingRemoved || shouldClear) {
                                mNonConfig.clearNonConfigState(f);
                            }
                            f.performDestroy();
                            dispatchOnFragmentDestroyed(f, false);
                        } else {
                            f.mState = Fragment.INITIALIZING;
                        }

                        f.performDetach();
                        dispatchOnFragmentDetached(f, false);
                        if (!keepActive) {
                            if (beingRemoved || mNonConfig.shouldDestroy(f)) {
                                makeInactive(f);
                            } else {
                                f.mHost = null;
                                f.mParentFragment = null;
                                f.mFragmentManager = null;
                                if (f.mTargetWho != null) {
                                    Fragment target = mActive.get(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 (f.mState != newState) {
        Log.w(TAG, "moveToState: Fragment state for " + f + " not updated inline; "
        + "expected state " + newState + " found " + f.mState);
        f.mState = newState;
    }
}

OP_REMOVE操作會把指定的fragment從FragmentManagerImpl中移除,移除過程中會視配置情況進行狀態保存、移除view、釋放fragment、FragmentManagerImpl調度其他fragment等處理。

REPLACE操作類型

通過調用FragmentTransaction的replace方法,傳入指定的佈局容器ID和fragment,達到替換佈局容器中的fragment的view。

[FragmentTransaction.java]

public FragmentTransaction replace(@IdRes int containerViewId, @NonNull Fragment fragment,
        @Nullable String tag)  {
    // 必須指定佈局容器ID
    if (containerViewId == 0) {
        throw new IllegalArgumentException("Must use non-zero containerViewId");
    }
    doAddOp(containerViewId, fragment, tag, OP_REPLACE);
    return this;
}

添加OP_REPLACE類型的Op到mOps集合中。

接着看執行命令操作的方法executeOpsTogether:
[FragmentManagerImpl.java]

private void executeOpsTogether(ArrayList<BackStackRecord> records,
                                ArrayList<Boolean> isRecordPop, int startIndex, int endIndex) {
    // ···
    for (int recordNum = startIndex; recordNum < endIndex; recordNum++) {
        final BackStackRecord record = records.get(recordNum);
        final boolean isPop = isRecordPop.get(recordNum);
        if (!isPop) {
            // 根據操作類型進行展開操作
            oldPrimaryNav = record.expandOps(mTmpAddedFragments, oldPrimaryNav);
        } else {
            oldPrimaryNav = record.trackAddedFragmentsInPop(mTmpAddedFragments, oldPrimaryNav);
        }
        addToBackStack = addToBackStack || record.mAddToBackStack;
    }
    // ···
    // 執行操作
    executeOps(records, isRecordPop, startIndex, endIndex);
    // ···
}

該方法中再執行命令操作前會先調用BackStackRecord的expandOps方法中根據操作類型進行展開操作。

[BackStackRecord.java]

Fragment expandOps(ArrayList<Fragment> added, Fragment oldPrimaryNav) {
    // 遍歷mOps集合中的Op
    for (int opNum = 0; opNum < mOps.size(); opNum++) {
        final Op op = mOps.get(opNum);
        switch (op.mCmd) {
            case OP_ADD:
            case OP_ATTACH:
                added.add(op.mFragment);
                break;
            case OP_REMOVE:
            case OP_DETACH: {
                added.remove(op.mFragment);
                if (op.mFragment == oldPrimaryNav) {
                    mOps.add(opNum, new Op(OP_UNSET_PRIMARY_NAV, op.mFragment));
                    opNum++;
                    oldPrimaryNav = null;
                }
            }
            break;
            case OP_REPLACE: {
                final Fragment f = op.mFragment;
                final int containerId = f.mContainerId;
                // 標記該fragment是否添加過
                boolean alreadyAdded = false;
                // 遍歷FragmentManagerImpl的mAdded中的Fragment
                for (int i = added.size() - 1; i >= 0; i--) {
                    final Fragment old = added.get(i);
                    // 判斷是否指定過相同的佈局容器ID
                    if (old.mContainerId == containerId) {
                        // 判斷指定了相同佈局容器的那個fragment是否就是這個fragment
                        if (old == f) {
                            // 標記爲true
                            alreadyAdded = true;
                        } else {
                            // This is duplicated from above since we only make
                            // a single pass for expanding ops. Unset any outgoing primary nav.
                            if (old == oldPrimaryNav) {
                                mOps.add(opNum, new Op(OP_UNSET_PRIMARY_NAV, old));
                                opNum++;
                                oldPrimaryNav = null;
                            }
                            // 創建OP_REMOVE的操作
                            final Op removeOp = new Op(OP_REMOVE, old);
                            removeOp.mEnterAnim = op.mEnterAnim;
                            removeOp.mPopEnterAnim = op.mPopEnterAnim;
                            removeOp.mExitAnim = op.mExitAnim;
                            removeOp.mPopExitAnim = op.mPopExitAnim;
                            // 添加進mOps中
                            mOps.add(opNum, removeOp);
                            // 移除指定的佈局容器中的那個fragment
                            added.remove(old);
                            opNum++;
                        }
                    }
                }
                if (alreadyAdded) {
                    // 若該fragment已經添加了,移除這個操作即可
                    mOps.remove(opNum);
                    opNum--;
                } else {
                    // 將這個操作的類型修改成OP_ADD
                    op.mCmd = OP_ADD;
                    // 將fragment添加進mAdded中
                    added.add(f);
                }
            }
            break;
            case OP_SET_PRIMARY_NAV: {
                // ···
            }
            break;
        }
    }
    return oldPrimaryNav;
}

可以看到OP_REPLACE操作其實是調整爲OP_REMOVE+OP_ADD。

HIDE和SHOW操作類型

通過FragmentTransaction的hide和show方法,可以將指定的fragment隱藏和顯示。
[FragmentTransaction.java]

public FragmentTransaction hide(@NonNull Fragment fragment) {
    addOp(new Op(OP_HIDE, fragment));

    return this;
}

public FragmentTransaction show(@NonNull Fragment fragment) {
    addOp(new Op(OP_SHOW, fragment));

    return this;
}

添加OP_HIDEOP_SHOW類型的命令。

接着看處理的部分,在executeOps方法的OP_HIDE case和OP_SHOW case中,會調用FragmentManagerImpl的hideFragment和showFragment方法:
[FragmentManagerImpl.java]

public void hideFragment(Fragment fragment) {
    if (DEBUG) Log.v(TAG, "hide: " + fragment);
    if (!fragment.mHidden) {
        // 將mHidden成員標記爲true
        fragment.mHidden = true;
        // Toggle hidden changed so that if a fragment goes through show/hide/show
        // it doesn't go through the animation.
        fragment.mHiddenChanged = !fragment.mHiddenChanged;
    }
}

public void showFragment(Fragment fragment) {
    if (DEBUG) Log.v(TAG, "show: " + fragment);
    if (fragment.mHidden) {
        // 將mHidden成員標記爲false
        fragment.mHidden = false;
        // Toggle hidden changed so that if a fragment goes through show/hide/show
        // it doesn't go through the animation.
        fragment.mHiddenChanged = !fragment.mHiddenChanged;
    }
}

Fragment中是通過mHidden成員來標記當前是要隱藏還是要顯示。

接下來在FragmentManagerImpl的moveToState方法中,會根據mHidden值來設置view的可見:
[FragmentManagerImpl.java]

void moveToState(Fragment f, int newState, int transit, int transitionStyle,
                 boolean keepActive) {
    // ···
    if (f.mState <= newState) {
        // ···
        switch (f.mState) {
            // ···
            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) {
                    // 該處理從xml文件中添加Fragment
                    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 (Resources.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.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);
                            }
                            // 在創建完view後,判斷mHidden是否爲true
                            if (f.mHidden) {
                                // 設置view爲GONE
                                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;
                }
            // ···
        }
    } else if (f.mState > newState) {
        // ···
    }
    // ···
}

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);
            // 若mHidden爲true,則將view設置爲GONE
            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;
        }
    }
}

若mHidden設置爲true,則會將通過Fragment創建的view的可見屬性設置爲GONE。

回到FragmentManagerImpl的moveFragmentToExpectedState方法:
[FragmentManagerImpl.java]

void moveFragmentToExpectedState(Fragment f) {
    // ···
    moveToState(f, nextState, f.getNextTransition(), f.getNextTransitionStyle(), false);
    // ···
    // mHiddenChanged默認爲false,當對fragment進行顯示隱藏操作變化時會變爲true
    if (f.mHiddenChanged) {
        completeShowHideFragment(f);
    }
}

該方法中在執行完moveToState方法將fragment調整到最終目標狀態後,在該方法的結尾會判斷調用completeShowHideFragment方法,進入這個方法看看做了什麼動作:
[FragmentManagerImpl.java]

void completeShowHideFragment(final Fragment fragment) {
    // 判斷該fragment中是否有創建view
    if (fragment.mView != null) {
        AnimationOrAnimator anim = loadAnimation(fragment, fragment.getNextTransition(),
                !fragment.mHidden, fragment.getNextTransitionStyle());
        // 判斷是否設置了Animator
        if (anim != null && anim.animator != null) {
            anim.animator.setTarget(fragment.mView);
            // 判斷該fragment是否隱藏
            if (fragment.mHidden) {
                // isHideReplaced方法判斷是否正在進行隱藏的過渡動畫中
                if (fragment.isHideReplaced()) {
                    // 正在進行隱藏的過渡動畫
                    fragment.setHideReplaced(false);
                } else {
                    // 設置進行隱藏的過渡動畫
                    final ViewGroup container = fragment.mContainer;
                    final View animatingView = fragment.mView;
                    container.startViewTransition(animatingView);
                    // Delay the actual hide operation until the animation finishes,
                    // otherwise the fragment will just immediately disappear
                    anim.animator.addListener(new AnimatorListenerAdapter() {
                        @Override
                        public void onAnimationEnd(Animator animation) {
                            container.endViewTransition(animatingView);
                            animation.removeListener(this);
                            if (fragment.mView != null && fragment.mHidden) {
                                fragment.mView.setVisibility(View.GONE);
                            }
                        }
                    });
                }
            } else {
                // 若爲顯示,則將fragment的view設置爲VISIBLE
                fragment.mView.setVisibility(View.VISIBLE);
            }
            anim.animator.start();
        } else {
            if (anim != null) {
                // 未設置Animator,但設置了Animation
                fragment.mView.startAnimation(anim.animation);
                anim.animation.start();
            }
            final int visibility = fragment.mHidden && !fragment.isHideReplaced()
                    ? View.GONE
                    : View.VISIBLE;
            // 設置fragment的view的可見屬性
            fragment.mView.setVisibility(visibility);
            if (fragment.isHideReplaced()) {
                fragment.setHideReplaced(false);
            }
        }
    }
    if (fragment.mAdded && isMenuAvailable(fragment)) {
        mNeedMenuInvalidate = true;
    }
    // 把mHiddenChanged成員置回false
    fragment.mHiddenChanged = false;
    // 回調onHiddenChanged方法
    fragment.onHiddenChanged(fragment.mHidden);
}

該方法中邏輯主要是過渡動畫和view可見屬性的設置。

總結

前文大致跟蹤了一個Fragment從新建到添加入FragmentActivity的過程。
首先FragmentManager將“添加Fragment”的行爲封裝成一個Op操作,再將Op加入一個事務BackStackRecord,然後將事務加入待執行隊列保存,之後通過Handler調度至主線程執行。
接着FragmentManager從遍歷待執行隊列中的事務,依次執行。執行過程中根據操作類型以及Fragment狀態和FragmentManager狀態,執行Fragment對應階段的處理和生命週期回調。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章