一窝爪、Fragment事務(wù)提交的部分操作
1.相關(guān)源碼概念
FragmetActivity的getSupportFragmentManager()內(nèi)部是通過FragmentController.getSupportFragmentManager嘉冒,而FragmentController的內(nèi)部是獲取的HostCallbacks對象中的FragmentManager對象象对,這個對象在最新版本的Androidx源碼中误证,雖然是FragmentManagerImpl對象,但是FragmentManagerImpl其實是一個空子類威鹿。
通過FragmentManager.beginTransaction()獲取FragmentTransaction對象钾怔,而FragmentManager.beginTransaction()中的方法實現(xiàn)如下:
public FragmentTransaction beginTransaction() {
return new BackStackRecord(this);
}
FragmentTransaction.add
FragmentTransaction.remove
FragmentTransaction.replace
FragmentTransaction.hide
FragmentTransaction.show
FragmentTransaction.setPrimaryNavigationFragment
FragmentTransaction.addToBackStack
FragmentTransaction.commit
FragmentTransaction的實現(xiàn)類只有一個BackStackRecord
其實這些所有的add、replace等境输,最終都是將Fragment的狀態(tài)變成了ADD蔗牡,然后最終在執(zhí)行的時候,都是通過調(diào)用FragmentManager.moveToState方法嗅剖,createView辩越,一直開始執(zhí)行生命周期,而在FragmentManager.moveToState方法中信粮,每個生命周期執(zhí)行完成之后黔攒,都會繼續(xù)調(diào)用moveToState轉(zhuǎn)成下一個步驟的生命周期狀態(tài)。
使用事務(wù)强缘,是為了保證連續(xù)的操作是原子性的督惰。
調(diào)用hide和show的時候,其實并不會去走生命周期旅掂。
2.FragmentActivity#getSupportFragmentManager()
該源碼邏輯在在上面已經(jīng)說了赏胚,這里就貼下源碼:
// FragmentActivity.java
public FragmentManager getSupportFragmentManager() {
// 這里的mFragments其實就是FragmentController對象
return mFragments.getSupportFragmentManager();
}
// FragmentController.java
public FragmentManager getSupportFragmentManager() {
// 獲取HostCallbacks對象中創(chuàng)建的FragmentManager對象
return mHost.mFragmentManager;
}
// FragmentHostCallback.java 這是HostCallbacks的父類,泛型是傳入的FragmentActivity
final FragmentManager mFragmentManager = new FragmentManagerImpl();
3.FragmentManager#beginTransaction
// 獲取事務(wù)類商虐,BackStackRecord其實就是FragmentTransaction的子類實現(xiàn)
public FragmentTransaction beginTransaction() {
return new BackStackRecord(this);
}
// 從BackStackRecord的源碼可以看出觉阅,BackStackRecord實現(xiàn)了FragmentTransaction抽象類
// 還實現(xiàn)了FragmentManager.OpGenerator接口,所以在這個流程中秘车,保存事務(wù)的時候典勇,可能會以FragmentManager.OpGenerator對象
// 也可能會以BackStackRecord保存,這是同一個叮趴。
final class BackStackRecord extends FragmentTransaction implements
FragmentManager.BackStackEntry, FragmentManager.OpGenerator {
4.FragmentTransaction#add
(1)直接傳入Fragment的Class對象割笙,在內(nèi)部創(chuàng)建Fragment
public final FragmentTransaction add(@NonNull Class<? extends Fragment> fragmentClass,
@Nullable Bundle args, @Nullable String tag) {
return add(createFragment(fragmentClass, args), tag);
}
public FragmentTransaction add(@NonNull Fragment fragment, @Nullable String tag) {
// 調(diào)用add方法,設(shè)置Op的mCmd指令為OP_ADD
doAddOp(0, fragment, tag, OP_ADD);
return this;
}
(2)傳入布局控件id和Fragment對象
public final FragmentTransaction add(@IdRes int containerViewId,
@NonNull Class<? extends Fragment> fragmentClass, @Nullable Bundle args) {
return add(containerViewId, createFragment(fragmentClass, args));
}
public FragmentTransaction add(@IdRes int containerViewId, @NonNull Fragment fragment) {
doAddOp(containerViewId, fragment, null, OP_ADD);
return this;
}
5.FragmentTransaction#doAddOp
如果傳入的是Fragment的Class對象眯亦,這doAddOp操作的第一個參數(shù)直接傳0伤溉,如果是傳入具體的containerViewId豪嚎,則使用具體的containerViewId
// 這步的主要操作就是設(shè)置tag和containerId
void doAddOp(int containerViewId, Fragment fragment, @Nullable String tag, int opcmd) {
final Class<?> fragmentClass = fragment.getClass();
final int modifiers = fragmentClass.getModifiers();
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) {
if (fragment.mTag != null && !tag.equals(fragment.mTag)) {
throw new IllegalStateException("Can't change tag of fragment "
+ fragment + ": was " + fragment.mTag
+ " now " + tag);
}
fragment.mTag = tag;
}
// 判斷布局id是否為0,如果不為0谈火,設(shè)置給fragment對象的mContainerId值
// 這是用于在fragment對象進行createView的時候使用
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");
}
if (fragment.mFragmentId != 0 && fragment.mFragmentId != containerViewId) {
throw new IllegalStateException("Can't change container ID of fragment "
+ fragment + ": was " + fragment.mFragmentId
+ " now " + containerViewId);
}
// 設(shè)置宿主ID為布局ID
fragment.mContainerId = fragment.mFragmentId = containerViewId;
}
// 將fragment和opcmd指令封裝成一個Op對象,Op對象其是對于Fragment的操作對象舌涨,封裝fragment的相關(guān)操作信息
addOp(new Op(opcmd, fragment));
}
6.FragmentTransaction#addOp
void addOp(Op op) {
// 將每個Fragment相關(guān)的操作對象添加到ArrayList集合中糯耍,用于提交的時候使用
mOps.add(op);
op.mEnterAnim = mEnterAnim;
op.mExitAnim = mExitAnim;
op.mPopEnterAnim = mPopEnterAnim;
op.mPopExitAnim = mPopExitAnim;
}
7.BackStackRecord#commit
BackStackRecord的提交有四個方法,這里做統(tǒng)一分析:然后最后就分析commit()的后續(xù)流程囊嘉,因為大體相同温技,主要就是異步和同步提交不同。
// commit() 在主線程中異步執(zhí)行扭粱,其實也是 Handler 拋出任務(wù)舵鳞,等待主線程調(diào)度執(zhí)行。
// commit需要在Activity保存狀態(tài)之前提交琢蛤,否則會報錯蜓堕。
// 因為Activity出現(xiàn)異常需要恢復(fù)狀態(tài),在保存狀態(tài)之后的commit會丟失
@Override
public int commit() {
return commitInternal(false);
}
// commitAllowingStateLoss() 也是異步執(zhí)行博其,但它的不同之處在于套才,允許在 Activity
// 保存狀態(tài)之后調(diào)用,也就是說它遇到狀態(tài)丟失不會報錯慕淡。
@Override
public int commitAllowingStateLoss() {
return commitInternal(true);
}
// 這是同步執(zhí)行的背伴。立即提交事務(wù)。與FragmentManager.executePendingTransactions
// 類似峰髓,但是推薦使用commitNow傻寂。因為executePendingTransactions會一次性
// 執(zhí)行所有待執(zhí)行的事務(wù),可能會有副作用疾掰。而且executePendingTransactions方法提交
// 的事務(wù)可能不會被添加到FragmentManager的回退棧中,因為這樣直接提交可能會影響
// 其他異步執(zhí)行任務(wù)在棧中的順序
// commitNow的提交也不能在狀態(tài)保存之后進行
// TODO:這兩個方法在調(diào)用的時候徐紧,是禁止使用回退棧功能的
@Override
public void commitNow() {
disallowAddToBackStack();
mManager.execSingleAction(this, false);
}
@Override
public void commitNowAllowingStateLoss() {
disallowAddToBackStack();
mManager.execSingleAction(this, true);
}
8.BackStackRecord#commitInternal
int commitInternal(boolean allowStateLoss) {
if (mCommitted) throw new IllegalStateException("commit already called");
if (FragmentManager.isLoggingEnabled(Log.VERBOSE)) {
Log.v(TAG, "Commit: " + this);
LogWriter logw = new LogWriter(TAG);
PrintWriter pw = new PrintWriter(logw);
dump(" ", pw);
pw.close();
}
mCommitted = true;
// 這里的index个绍,其實是記錄當(dāng)前事務(wù)可以放置的位置的
// 如果是fragment-1.1.0版本,是采用兩個集合的方式浪汪,一個集合保存BackStackRecord
// 另一個集合保存因為回退之后巴柿,空出來的位置的索引
// 但是在fragment-1.2.1版本中,采用的是AtomicInteger死遭,比較并交換的做法
if (mAddToBackStack) {
// 這里是回退椆慊郑可用的情況,則需要計算一個index
// 這里因為Androidx版本的區(qū)別呀潭,實現(xiàn)也不同钉迷。
// 這里的代碼是fragment-1.2.1版本的庫
mIndex = mManager.allocBackStackIndex();
// 如果是fragment-1.1.0的庫至非,則與這里實現(xiàn)不同,如下所示
// mIndex = mManager.allocBackStackIndex(this);
} else {
mIndex = -1;
}
mManager.enqueueAction(this, allowStateLoss);
return mIndex;
}
9.FragmentManager#allocBackStackIndex()
這是fragment-1.2.1-androidx的源碼
這里采用AtomicInteger糠聪,是為了保證在異步提交事務(wù)處理的時候荒椭,保證index的一個原子性
int allocBackStackIndex() {
return mBackStackIndex.getAndIncrement();
}
對比fragment-1.1.0-androidx的源碼
在這里,是采用兩個ArrayList數(shù)組的方式舰蟆,一個用來保存當(dāng)前提交的事務(wù)趣惠,而另一個是用來保存當(dāng)前事務(wù)集合中的可用位置,這樣說可能比較抽象身害,看源碼分析味悄。
public int allocBackStackIndex(BackStackRecord bse) {
synchronized (this) {
// 第一次提交的時候,mAvailBackStackIndices是為null或者size==0的
// 所以執(zhí)行if條件
if (mAvailBackStackIndices == null || mAvailBackStackIndices.size() <= 0) {
// 初始化mBackStackIndices保存事務(wù)
if (mBackStackIndices == null) {
mBackStackIndices = new ArrayList<BackStackRecord>();
}
// 找到當(dāng)前添加的事務(wù)的索引位置塌鸯,在這里侍瑟,因為是添加到了mBackStackIndices的末尾
// 所以添加的集合的索引位置其實就是添加之前的集合的長度
int index = mBackStackIndices.size();
if (DEBUG) Log.v(TAG, "Setting back stack index " + index + " to " + bse);
mBackStackIndices.add(bse);
return index;
} else {
int index = mAvailBackStackIndices.remove(mAvailBackStackIndices.size()-1);
if (DEBUG) Log.v(TAG, "Adding back stack index " + index + " with " + bse);
mBackStackIndices.set(index, bse);
return index;
}
}
}
// 向之前回退位置的存儲集合位置上添加事務(wù)
public void setBackStackIndex(int index, BackStackRecord bse) {
synchronized (this) {
if (mBackStackIndices == null) {
mBackStackIndices = new ArrayList<BackStackRecord>();
}
int N = mBackStackIndices.size();
// 如果index小于mBackStackIndices的長度,說明mBackStackIndices中有取出添加到回退棧的事務(wù)
// 那么基于復(fù)用原則丙猬,繼續(xù)復(fù)用之前取出的位置存放當(dāng)前添加的事務(wù)
if (index < N) {
if (DEBUG) Log.v(TAG, "Setting back stack index " + index + " to " + bse);
mBackStackIndices.set(index, bse);
} else {
// 如果存儲集合的長度是小于要添加的位置涨颜,則向集合的末尾添加事務(wù)
while (N < index) {
mBackStackIndices.add(null);
if (mAvailBackStackIndices == null) {
mAvailBackStackIndices = new ArrayList<Integer>();
}
if (DEBUG) Log.v(TAG, "Adding available back stack index " + N);
mAvailBackStackIndices.add(N);
N++;
}
if (DEBUG) Log.v(TAG, "Adding back stack index " + index + " with " + bse);
// 這里是index==N的條件
mBackStackIndices.add(bse);
}
}
}
// 釋放存儲事務(wù)集合中的事務(wù)
public void freeBackStackIndex(int index) {
synchronized (this) {
// 在釋放mBackStackIndices中的事務(wù)的時候,并不是單純的將集合的index位置釋放茧球,然后重新排序集合
// 而是采用一個null來填充咐低,用于下一次的復(fù)用
mBackStackIndices.set(index, null);
if (mAvailBackStackIndices == null) {
mAvailBackStackIndices = new ArrayList<Integer>();
}
if (DEBUG) Log.v(TAG, "Freeing back stack index " + index);
// 這里存儲的其實就是之前被釋放的事務(wù)的位置,這樣的做法袜腥,其實就是方便
// 下一次添加事務(wù)的時候见擦,能夠精準的找到mBackStackIndices中對應(yīng)的位置存放事務(wù)
mAvailBackStackIndices.add(index);
}
}
10.FragmentManager#enqueueAction
void enqueueAction(@NonNull OpGenerator action, boolean allowStateLoss) {
// 判斷是否需要檢查狀態(tài),即是否允許在保存狀態(tài)之后提交事務(wù)進行丟棄
// 如果allowStateLoss是false羹令,則需要檢查當(dāng)前事務(wù)提交的時候是否已經(jīng)進行onSaveInstanceState操作
if (!allowStateLoss) {
if (mHost == null) {
if (mDestroyed) {
throw new IllegalStateException("FragmentManager has been destroyed");
} else {
throw new IllegalStateException("FragmentManager has not been attached to a "
+ "host.");
}
}
checkStateLoss();
}
// mPendingActions中添加的是正在等待處理的事務(wù)
synchronized (mPendingActions) {
// 如果HostCallbacks對象為null鲤屡,判斷allowStateLoss是否為true
// 如果為true,則直接return福侈,否則拋出異常酒来,提示activity已經(jīng)被銷毀
if (mHost == null) {
if (allowStateLoss) {
// This FragmentManager isn't attached, so drop the entire transaction.
return;
}
throw new IllegalStateException("Activity has been destroyed");
}
mPendingActions.add(action);
// 異步執(zhí)行提交操作
scheduleCommit();
}
}
11.FragmentManager#scheduleCommit
// 執(zhí)行異步任務(wù)
void scheduleCommit() {
synchronized (mPendingActions) {
boolean postponeReady =
mPostponedTransactions != null && !mPostponedTransactions.isEmpty();
boolean pendingReady = mPendingActions.size() == 1;
if (postponeReady || pendingReady) {
// 這里就是采用之前添加到HostCallbacks對象中的Handler來執(zhí)行異步任務(wù)操作
// 首先刪除上一次執(zhí)行的提交的任務(wù)
mHost.getHandler().removeCallbacks(mExecCommit);
// 然后再執(zhí)行當(dāng)前新的提交請求
// mExecCommit其實是一個Runnable對象
mHost.getHandler().post(mExecCommit);
updateOnBackPressedCallbackEnabled();
}
}
}
12.FragmentManager#mExecCommit對象
private Runnable mExecCommit = new Runnable() {
@Override
public void run() {
// 由HostCallbacks中的Handler進行執(zhí)行該任務(wù)
execPendingActions(true);
}
};
13.FragmentManager#execPendingActions
// 只能從主線程調(diào)用該方法
boolean execPendingActions(boolean allowStateLoss) {
// 確保執(zhí)行是處于就緒階段,即沒有正在執(zhí)行的事務(wù)肪凛,也HostCallbacks也不為null
// 且是在主線程中堰汉,并且初始化mTmpRecords和mTmpIsPop
// 這里就是針對execPendingActions的方法執(zhí)行的線程檢查的操作
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進行了add
// 又進行了remove就乓,然后又進行了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ù)志衣,進行強制執(zhí)行
// 不過這些事務(wù)是過去延遲處理屯援,但是當(dāng)前已經(jīng)準備好的事務(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;
// 添加Fragment到集合中,該集合是ADD狀態(tài)的Fragment集合
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操作,這里其實就是想ADD狀態(tài)集合添加Fragment
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();
}
}
16.BackStackRecord#expandOps
這里主要是找到舊的Fragment的導(dǎo)航
Fragment expandOps(ArrayList<Fragment> added, Fragment oldPrimaryNav) {
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: {
// REPLACE狀態(tài)耳胎,如果是已經(jīng)添加的惯吕,則需要刪除已經(jīng)添加的,然后再一次添加新的
final Fragment f = op.mFragment;
final int containerId = f.mContainerId;
boolean alreadyAdded = false;
for (int i = added.size() - 1; i >= 0; i--) {
final Fragment old = added.get(i);
if (old.mContainerId == containerId) {
// 判斷舊的Fragment和當(dāng)前要添加的Fragment是否一致
if (old == f) {
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;
}
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.add(opNum, removeOp);
added.remove(old);
opNum++;
}
}
}
// 如果是已經(jīng)添加怕午,則先刪除已經(jīng)添加的废登,然后在加入新的
// 再將op.mCmd改成OP_ADD
if (alreadyAdded) {
mOps.remove(opNum);
opNum--;
} else {
op.mCmd = OP_ADD;
added.add(f);
}
}
break;
case OP_SET_PRIMARY_NAV: {
// It's ok if this is null, that means we will restore to no active
// primary navigation fragment on a pop.
mOps.add(opNum, new Op(OP_UNSET_PRIMARY_NAV, oldPrimaryNav));
opNum++;
// Will be set by the OP_SET_PRIMARY_NAV we inserted before when run
oldPrimaryNav = op.mFragment;
}
break;
}
}
return oldPrimaryNav;
}
17.FragmentManager#executeOps
private static void executeOps(@NonNull ArrayList<BackStackRecord> records,
@NonNull 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);
// 執(zhí)行事務(wù)
record.executeOps();
}
}
}
18.BackStackRecord#executeOps
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);
}
switch (op.mCmd) {
case OP_ADD:
f.setNextAnim(op.mEnterAnim);
mManager.setExitAnimationOrder(f, false);
mManager.addFragment(f);
break;
case OP_REMOVE:
f.setNextAnim(op.mExitAnim);
mManager.removeFragment(f);
break;
case OP_HIDE:
f.setNextAnim(op.mExitAnim);
mManager.hideFragment(f);
break;
case OP_SHOW:
f.setNextAnim(op.mEnterAnim);
mManager.setExitAnimationOrder(f, false);
mManager.showFragment(f);
break;
case OP_DETACH:
f.setNextAnim(op.mExitAnim);
mManager.detachFragment(f);
break;
case OP_ATTACH:
f.setNextAnim(op.mEnterAnim);
mManager.setExitAnimationOrder(f, false);
mManager.attachFragment(f);
break;
case OP_SET_PRIMARY_NAV:
mManager.setPrimaryNavigationFragment(f);
break;
case OP_UNSET_PRIMARY_NAV:
mManager.setPrimaryNavigationFragment(null);
break;
case OP_SET_MAX_LIFECYCLE:
mManager.setMaxLifecycle(f, op.mCurrentMaxState);
break;
default:
throw new IllegalArgumentException("Unknown cmd: " + op.mCmd);
}
if (!mReorderingAllowed && op.mCmd != OP_ADD && f != null) {
mManager.moveFragmentToExpectedState(f);
}
}
if (!mReorderingAllowed) {
// 事務(wù)提交之后,根據(jù)當(dāng)前狀態(tài)郁惜,執(zhí)行fragment的生命周期
mManager.moveToState(mManager.mCurState, true);
}
}
19.FragmentManager#addFragment/removeFragment/hideFragment/showFragment/detachFragment/attachFragment
void addFragment(@NonNull Fragment fragment) {
if (isLoggingEnabled(Log.VERBOSE)) Log.v(TAG, "add: " + fragment);
makeActive(fragment);
if (!fragment.mDetached) {
// 向mAdded集合中添加fragment堡距,mAdded集合是保存添加的Fragment
// 用于在moveToState的處理添加的Fragment
mFragmentStore.addFragment(fragment);
fragment.mRemoving = false;
if (fragment.mView == null) {
// 添加之后,設(shè)置隱藏狀態(tài)為false
fragment.mHiddenChanged = false;
}
if (isMenuAvailable(fragment)) {
mNeedMenuInvalidate = true;
}
}
}
void removeFragment(@NonNull Fragment fragment) {
if (isLoggingEnabled(Log.VERBOSE)) {
Log.v(TAG, "remove: " + fragment + " nesting=" + fragment.mBackStackNesting);
}
final boolean inactive = !fragment.isInBackStack();
if (!fragment.mDetached || inactive) {
// 從mAdded集合中刪除fragment
mFragmentStore.removeFragment(fragment);
if (isMenuAvailable(fragment)) {
mNeedMenuInvalidate = true;
}
fragment.mRemoving = true;
setVisibleRemovingFragment(fragment);
}
}
void hideFragment(@NonNull Fragment fragment) {
if (isLoggingEnabled(Log.VERBOSE)) Log.v(TAG, "hide: " + fragment);
if (!fragment.mHidden) {
// 設(shè)置fragment的隱藏狀態(tài)為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;
setVisibleRemovingFragment(fragment);
}
}
void showFragment(@NonNull Fragment fragment) {
if (isLoggingEnabled(Log.VERBOSE)) Log.v(TAG, "show: " + fragment);
if (fragment.mHidden) {
// 設(shè)置fragment的隱藏狀態(tài)
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;
}
}
void detachFragment(@NonNull Fragment fragment) {
if (isLoggingEnabled(Log.VERBOSE)) Log.v(TAG, "detach: " + fragment);
if (!fragment.mDetached) {
fragment.mDetached = true;
if (fragment.mAdded) {
// We are not already in back stack, so need to remove the fragment.
if (isLoggingEnabled(Log.VERBOSE)) Log.v(TAG, "remove from detach: " + fragment);
mFragmentStore.removeFragment(fragment);
if (isMenuAvailable(fragment)) {
mNeedMenuInvalidate = true;
}
setVisibleRemovingFragment(fragment);
}
}
}
void attachFragment(@NonNull Fragment fragment) {
if (isLoggingEnabled(Log.VERBOSE)) Log.v(TAG, "attach: " + fragment);
if (fragment.mDetached) {
fragment.mDetached = false;
if (!fragment.mAdded) {
mFragmentStore.addFragment(fragment);
if (isLoggingEnabled(Log.VERBOSE)) Log.v(TAG, "add from attach: " + fragment);
if (isMenuAvailable(fragment)) {
mNeedMenuInvalidate = true;
}
}
}
}
20.FragmentManager#moveToState
void moveToState(int newState, boolean always) {
if (mHost == null && newState != Fragment.INITIALIZING) {
throw new IllegalStateException("No activity");
}
if (!always && newState == mCurState) {
return;
}
mCurState = newState;
// Must add them in the proper order. mActive fragments may be out of order
for (Fragment f : mFragmentStore.getFragments()) {
moveFragmentToExpectedState(f);
}
// Now iterate through all active fragments. These will include those that are removed
// and detached.
for (Fragment f : mFragmentStore.getActiveFragments()) {
if (f != null && !f.mIsNewlyAdded) {
moveFragmentToExpectedState(f);
}
}
startPendingDeferredFragments();
if (mNeedMenuInvalidate && mHost != null && mCurState == Fragment.RESUMED) {
mHost.onSupportInvalidateOptionsMenu();
mNeedMenuInvalidate = false;
}
}
21.FragmentManager#moveFragmentToExpectedState
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;
}
// 在CREATED狀態(tài)的時候會創(chuàng)建View兆蕉,保存在Fragment
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();
}
}
}
}
// 是否隱藏的狀態(tài)羽戒,如果是true,這執(zhí)行完成隱藏顯示Fragment的操作
if (f.mHiddenChanged) {
completeShowHideFragment(f);
}
}