從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();
}
}