咱們常常用到Fragment,可是你到底用過幾種方式呢,今天咱們就從最經常使用的一種開始分析,順便也看一看其它的幾種方法吧。咱們的源碼分析開始咯,源碼分析第...幾篇,算了這些不重要,趁着最近不是很忙「燥起來」。html
咱們平常使用Fragment無非就幾種:replace和add、hide、show,如下面這種爲例:android
Fragment testFragment=new TestFragment();
//獲取FragmentManager
FragmentManager fm = getFragmentManager();// 或者getSupportFragmentManager();
//獲取FragmentTransaction
FragmentTransaction ft = fm.beginTransaction();
//進行添加操做
ft.add(R.id.fragment_container,testFragment);
// 顯示
ft.show(testFragment);
//提交
ft.commit();
複製代碼
那咱們接下來就按照以上這種順序來分析一下Fragment的加載過程。api
先看一下使用getFragmentManager()方法獲取FragmentManager數組
// Activity類:
@Deprecated
public FragmentManager getFragmentManager() {
return mFragments.getFragmentManager();
}
複製代碼
因爲本文是以android-28爲基礎的源碼分析,而在api28中getFragmentManager()這種方式已被棄用,官方建議使用官方建議使用android.support.v4.app.Fragment來替代android.app.Fragment,使用android.support.v4.app.FragmentManager來替代android.app.FragmentManager,所以咱們本文以getSupportFragmentManager()方法獲取FragmentManager來繼續分析。而使用getSupportFragmentManager()方法當前Activity就必須繼承於FragmentActivity以及其子類。bash
// FragmentActivity類:
final FragmentController mFragments = FragmentController.createController(new FragmentActivity.HostCallbacks());
public FragmentManager getSupportFragmentManager() {
return this.mFragments.getSupportFragmentManager();
}
// 內部類
class HostCallbacks extends FragmentHostCallback<FragmentActivity> {
public HostCallbacks() {
super(FragmentActivity.this);
}
......
}
// FragmentController類:
private final FragmentHostCallback<?> mHost;
public static FragmentController createController(FragmentHostCallback<?> callbacks) {
return new FragmentController(callbacks);
}
private FragmentController(FragmentHostCallback<?> callbacks) {
this.mHost = callbacks;
}
public FragmentManager getSupportFragmentManager() {
return this.mHost.getFragmentManagerImpl();
}
// FragmentHostCallback類:
FragmentHostCallback(@NonNull FragmentActivity activity) {
// 關注一下第三個參數activity.mHandler
this(activity, activity, activity.mHandler, 0);
}
FragmentHostCallback(@Nullable Activity activity, @NonNull Context context, @NonNull Handler handler, int windowAnimations) {
// 初始化了FragmentManagerImpl類
this.mFragmentManager = new FragmentManagerImpl();
this.mActivity = activity;
this.mContext = (Context)Preconditions.checkNotNull(context, "context == null");
// 初始化了Handler,該mHandler會在commit操做中用到
this.mHandler = (Handler)Preconditions.checkNotNull(handler, "handler == null");
this.mWindowAnimations = windowAnimations;
}
FragmentManagerImpl getFragmentManagerImpl() {
return this.mFragmentManager;
}
// FragmentManagerImpl類:
final class FragmentManagerImpl extends FragmentManager implements Factory2
複製代碼
哈哈,爲了方便就直接將該部分相關代碼直接放在一塊兒啦,不要慌,咱們一步一步講起:app
經過上面展現的代碼以及所描述的5步說明,咱們能夠很清晰的看到mFragments被final修飾並且又是類成員,所以一個FragmentActivity對應一個FragmentController、一個FragmentHostCallback和一個FragmentManagerImpl。異步
從上面部分,咱們知道了fm其實就是FragmentManagerImpl類,因此咱們第二部分就是調用fm.beginTransaction()方法:ide
// FragmentManagerImpl類:
public FragmentTransaction beginTransaction() {
return new BackStackRecord(this);
}
// BackStackRecord類:
final class BackStackRecord extends FragmentTransaction
implements BackStackEntry, OpGenerator {
......
public BackStackRecord(FragmentManagerImpl manager) {
this.mManager = manager;
}
...
}
複製代碼
這部分顯的很單調,沒錯,這部分就這些內容,其實就是返回了繼承於FragmentTransaction的BackStackRecord類。注意啦BackStackRecord類很重要,很是重要。本文以android-28爲標準而講解,而本類在28中修改很大,28以前的版本BackStackRecord實現了Runnable接口,具體的可自行查看。該類直譯過來可被稱爲:返回堆棧記錄,此後的有關fragment的基本全部操做都是經過它來完成,咱們後續再詳細說明。函數
在第二部分中咱們知道ft指的是BackStackRecord類,咱們來看一下它的add方法:oop
// BackStackRecord類:
ArrayList<BackStackRecord.Op> mOps = new ArrayList();
public FragmentTransaction add(Fragment fragment, @Nullable String tag) {
this.doAddOp(0, fragment, tag, 1);
return this;
}
private void doAddOp(int containerViewId, Fragment fragment, @Nullable String tag, int opcmd) {
// 獲取fragment的Class對象
Class fragmentClass = fragment.getClass();
// 獲取該fragment對象的修飾符
int modifiers = fragmentClass.getModifiers();
// 如該fragment爲:匿名類或者不是public修飾符標識的類或者(它是內部類且不是靜態的)
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.");
} else {
fragment.mFragmentManager = this.mManager;
if (tag != null) {
// 防止同一個fragment被add屢次而且設置了多個不一樣的tag
// 若是tag不等於空,而且tag不等於fragment.mTag
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;
}
if (containerViewId != 0) {
// 容器視圖id,即FrameLayout佈局id
if (containerViewId == -1) {
throw new IllegalArgumentException("Can't add fragment " + fragment + " with tag " + tag + " to container view with no id");
}
// 方法屢次add其containerViewId且設置多個不一樣的containerViewId
if (fragment.mFragmentId != 0 && fragment.mFragmentId != containerViewId) {
throw new IllegalStateException("Can't change container ID of fragment " + fragment + ": was " + fragment.mFragmentId + " now " + containerViewId);
}
fragment.mContainerId = fragment.mFragmentId = containerViewId;
}
this.addOp(new BackStackRecord.Op(opcmd, fragment));
}
}
void addOp(BackStackRecord.Op op) {
this.mOps.add(op);
op.enterAnim = this.mEnterAnim;
op.exitAnim = this.mExitAnim;
op.popEnterAnim = this.mPopEnterAnim;
op.popExitAnim = this.mPopExitAnim;
}
// BackStackRecord內部類Op:
static final class Op {
int cmd;//指令:表明對fragment的操做,好比:add==1
Fragment fragment;//保存要操做的fragment
// 如下四個爲動畫設置
int enterAnim;
int exitAnim;
int popEnterAnim;
int popExitAnim;
Op() {
}
Op(int cmd, Fragment fragment) {
this.cmd = cmd;
this.fragment = fragment;
}
}
複製代碼
再次將此部分有關代碼放到了一塊兒,接着一步一步說明一下吧:
第三部分是否是也很簡單的樣子,那咱們繼續吧!!!
直接上代碼:
// BackStackRecord類:
public FragmentTransaction show(Fragment fragment) {
this.addOp(new BackStackRecord.Op(5, fragment));
return this;
}
複製代碼
經過第三部分的瞭解,咱們能夠很清晰的看出來,show操做其實只是調用addOp(new BackStackRecord.Op(5, fragment))方法,設置一下Op類的cmd指令。
其實上面的四部分都是比較好理解的,接下來將進入最後一部分,也是本文的最複雜最重要的部分
// BackStackRecord類:
public int commit() {
return this.commitInternal(false); // 注意這個false哦
}
int commitInternal(boolean allowStateLoss) {
// 若重複commit,則會拋出此異常
if (this.mCommitted) {
throw new IllegalStateException("commit already called");
} else {
if (FragmentManagerImpl.DEBUG) {
Log.v("FragmentManager", "Commit: " + this);
LogWriter logw = new LogWriter("FragmentManager");
PrintWriter pw = new PrintWriter(logw);
this.dump(" ", (FileDescriptor)null, pw, (String[])null);
pw.close();
}
this.mCommitted = true;
// 這個成員默認是false,只有咱們本身調用了addToBackStack方法,纔會設置爲true
if (this.mAddToBackStack) {
this.mIndex = this.mManager.allocBackStackIndex(this);
} else {
this.mIndex = -1;
}
// 此mManager咱們上面第一部分講解過,實際爲FragmentManagerImpl類
this.mManager.enqueueAction(this, allowStateLoss);
return this.mIndex;
}
}
// FragmentManagerImpl類:
// 注意:參數action爲BackStackRecord類,而allowStateLoss爲false,上面有說明
public void enqueueAction(FragmentManagerImpl.OpGenerator action, boolean allowStateLoss) {
if (!allowStateLoss) {
// 狀態丟失的異常檢查(具體請參考:https://www.jianshu.com/p/aa735c60c867)
// 若是咱們提交使用的是commit方法,則會走到該判斷裏來,由於commit方法allowStateLoss傳的是false。若是咱們提交使用的是commitAllowingStateLoss方法,則不會走到該判斷中來,由於commitAllowingStateLoss方法傳入的allowStateLoss爲true
this.checkStateLoss();
}
synchronized(this) {
if (!this.mDestroyed && this.mHost != null) {
if (this.mPendingActions == null) {
this.mPendingActions = new ArrayList();
}
// 加入待定任務隊列中,mPendingActions是ArrayList
this.mPendingActions.add(action);
this.scheduleCommit();
} else if (!allowStateLoss) {
throw new IllegalStateException("Activity has been destroyed");
}
}
}
void scheduleCommit() {
synchronized(this) {
boolean postponeReady = this.mPostponedTransactions != null && !this.mPostponedTransactions.isEmpty();
boolean pendingReady = this.mPendingActions != null && this.mPendingActions.size() == 1;
if (postponeReady || pendingReady) {
this.mHost.getHandler().removeCallbacks(this.mExecCommit);
this.mHost.getHandler().post(this.mExecCommit);
}
}
}
// " ***特別說明*** "
private void checkStateLoss() {
if (this.isStateSaved()) {
throw new IllegalStateException("Can not perform this action after onSaveInstanceState");
} else if (this.mNoTransactionsBecause != null) {
throw new IllegalStateException("Can not perform this action inside of " + this.mNoTransactionsBecause);
}
}
/**
* mStateSaved:fragment保存、恢復過程--fragment保存標識
* 由Activity.onSaveInstanceState方法最終會調到FragmentManagerImpl.saveAllState方法中設置mStateSaved爲true
* mStopped :fragment onStop週期的分發方法FragmentManagerImpl.dispatchStop()中設置爲true,此時Activity的週期也是onStop
*/
public boolean isStateSaved() {
return this.mStateSaved || this.mStopped;
}
// " ***特別說明*** "
複製代碼
先貼出該部分的中的部分代碼,咱們來分析一下:
從上面的三步中咱們瞭解到了,如今邏輯以及到了mExecCommit(Runnable)的run方法裏,咱們先不急看run()方法,咱們回來看一下enqueueAction()方法爲何把action添加進入mPendingActions裏?由於從後面的代碼中能夠了解每次commit後都會將mPendingActions集合清空,那爲何還要使用集合保存呢?不知作別的小夥伴有沒有這方面的糾結,我一開始反正是糾結的。那咱們來分析一下使用mPendingActions的緣由:咱們知道了commit的後續操做是在mExecCommit(Runnable)的run方法裏,而mExecCommit又是經過Handler看成消息post出去的,所以這裏就能夠把commit操做看成是在異步中執行的邏輯。這又是什麼緣由呢?那是由於Handler發出去的消息並非被Looper立刻執行的,而是須要先從消息隊列中取出來再去執行,所以在這個空隙,咱們能夠會屢次切換fragment(場景:app的首頁是由底部多個Tab+多個fragmnet實現,咱們頻繁屢次切換tab)而致使屢次生成action,所以須要一個集合來看成隊列將多個action添加進去,在後面統一處理。
這裏咱們再說一下幾種提交操做的方法:
commit() vs commitAllowingStateLoss()
用commit()提交有時候會遇到IllegalStateException, 說你在onSaveInstanceState()以後提交, commit()和commitAllowingStateLoss()在實現上惟一的不一樣就是當你調用commit()的時候, FragmentManger會檢查是否已經存儲了它本身的狀態, 若是已經存了, 就拋出IllegalStateException。 那麼若是你調用的是commitAllowingStateLoss(),則FragmentManger不會檢查是否已經存儲了它本身的狀態(上面代碼中已添加備註說明),而且要是在onSaveInstanceState()以後,你可能會丟失掉什麼狀態呢? 答案是你可能會丟掉FragmentManager的狀態, 即save以後任何被添加或被移除的Fragments.
commit(), commitNow() 和 executePendingTransactions()
使用commit()的時候, 一旦調用, 這個commit並非當即執行的, 它會被髮送到主線程的任務隊列當中去, 當主線程準備好執行它的時候執行. popBackStack()的工做也是這樣, 發送到主線程任務隊列中去. 也即說它們都是異步的.可是有時候你但願你的操做是當即執行的,以前的開發者會在commit()調用以後加上 executePendingTransactions()來保證當即執行, 即變異步爲同步.support library從v24.0.0開始提供了 commitNow()方法,以前用executePendingTransactions()會將全部pending在隊列中還有你新提交的transactions都執行了, 而commitNow()將只會執行你當前要提交的transaction. 因此commitNow()避免你會不當心執行了那些你可能並不想執行的transactions.
可是你不能對要加在back stack中的transaction使用commitNow(),即addToBackStack()和commitNow()不能同時使用.爲何呢? 想一想一下, 若是你有一個提交使用了commit(), 緊接着又有另外一個提交使用了commitNow(), 兩個都想加入back stack, 那back stack會變成什麼樣呢? 究竟是哪一個transaction在上, 哪一個在下? 答案將是一種不肯定的狀態, 由於系統並無提供任何保證來確保順序, 因此係統決定乾脆不支持這個操做.前面提過popBackStack()是異步的, 因此它一樣也有一個同步的兄弟popBackStackImmediate().因此實際應用的時候怎麼選擇呢? 1.若是你須要同步的操做, 而且你不須要加到back stack裏, 使用commitNow(). support library在FragmentPagerAdapter裏就使用了commitNow()來保證在更新結束的時候, 正確的頁面被加上或移除. 2.若是你操做不少transactions, 而且不須要同步, 或者你須要把transactions加在back stack裏, 那就使用commit(). 3.若是你但願在某一個指定的點, 確保全部的transactions都被執行, 那麼使用executePendingTransactions().
特別說明:若是項目中遇到須要在FragmentActivity的週期方法onStop(即不可見)後,切換fragment,則須要使用commitAllowingStateLoss()方法。具體緣由可參考上面代碼中的特別說明:當Activity和fragment處理onStop週期後,則會拋出異常
好啦,咱們能夠繼續分析接下的啦(mExecCommit(Runnable)的run方法):
// FragmentManagerImpl類:
Runnable mExecCommit = new Runnable() {
public void run() {
FragmentManagerImpl.this.execPendingActions();
}
};
public boolean execPendingActions() {
this.ensureExecReady(true);
boolean didSomething;
// mTmpRecords:臨時存儲全部待執行的動做(mPendingActions)生成的 BackStackRecord
// mTmpIsPop:存儲 BackStackRecord 是否爲出棧。
for(didSomething = false; this.generateOpsForPendingActions(this.mTmpRecords, this.mTmpIsPop); didSomething = true) {
this.mExecutingActions = true;
try {
this.removeRedundantOperationsAndExecute(this.mTmpRecords, this.mTmpIsPop);
} finally {
this.cleanupExec();
}
}
this.doPendingDeferredStart();
this.burpActive();
return didSomething;
}
// 遍歷 mPendingActions 調用 OpGenerator.generateOps() 方法生成 BackStackRecord 添加到 mTmpRecords 並把是否爲出棧添加到 mTmpIsPop 中
private boolean generateOpsForPendingActions(ArrayList<BackStackRecord> records, ArrayList<Boolean> isPop) {
boolean didSomething = false;
synchronized(this) {
if (this.mPendingActions != null && this.mPendingActions.size() != 0) {
int numActions = this.mPendingActions.size();
for(int i = 0; i < numActions; ++i) {
didSomething |= ((FragmentManagerImpl.OpGenerator)this.mPendingActions.get(i)).generateOps(records, isPop);
}
// 清空待定任務隊列
this.mPendingActions.clear();
this.mHost.getHandler().removeCallbacks(this.mExecCommit);
return didSomething;
} else {
return false;
}
}
}
// BackStackRecord類
public boolean generateOps(ArrayList<BackStackRecord> records, ArrayList<Boolean> isRecordPop) {
if (FragmentManagerImpl.DEBUG) {
Log.v("FragmentManager", "Run: " + this);
}
records.add(this);
// 添加false
isRecordPop.add(false);
if (this.mAddToBackStack) {
// 添加到「回退棧」中
this.mManager.addBackStackState(this);
}
return true;
}
// FragmentManagerImpl類的內部類PopBackStackState:
private class PopBackStackState implements FragmentManagerImpl.OpGenerator {
...
public boolean generateOps(ArrayList<BackStackRecord> records, ArrayList<Boolean> isRecordPop) {
...
return FragmentManagerImpl.this.popBackStackState(records, isRecordPop, this.mName, this.mId, this.mFlags);
}
}
// FragmentManagerImpl類:
boolean popBackStackState(ArrayList<BackStackRecord> records, ArrayList<Boolean> isRecordPop, String name, int id, int flags) {
if (this.mBackStack == null) {
return false;
} else {
int index;
if (name == null && id < 0 && (flags & 1) == 0) {
...
records.add(this.mBackStack.remove(index));
// 添加true
isRecordPop.add(true);
} else {
...
for(int i = this.mBackStack.size() - 1; i > index; --i) {
records.add(this.mBackStack.remove(i));
// 添加true
isRecordPop.add(true);
}
}
return true;
}
}
void addBackStackState(BackStackRecord state) {
if (this.mBackStack == null) {
this.mBackStack = new ArrayList();
}
// 「回退棧」 == mBackStack(ArrayList<BackStackRecord>)
this.mBackStack.add(state);
}
複製代碼
在 Runnable 中執行 execPendingActions() 方法,該方法分爲幾點來分析:
// FragmentManagerImpl類:
private void removeRedundantOperationsAndExecute(ArrayList<BackStackRecord> records, ArrayList<Boolean> isRecordPop) {
if (records != null && !records.isEmpty()) {
if (isRecordPop != null && records.size() == isRecordPop.size()) {
this.executePostponedTransaction(records, isRecordPop);
int numRecords = records.size();
int startIndex = 0;
for(int recordNum = 0; recordNum < numRecords; ++recordNum) {
boolean canReorder = ((BackStackRecord)records.get(recordNum)).mReorderingAllowed;
if (!canReorder) {
if (startIndex != recordNum) {
this.executeOpsTogether(records, isRecordPop, startIndex, recordNum);
}
int reorderingEnd = recordNum + 1;
// 根據上面的分析,只有「回退棧」執行出棧纔會執行此處代碼
if ((Boolean)isRecordPop.get(recordNum)) {
while(reorderingEnd < numRecords && (Boolean)isRecordPop.get(reorderingEnd) && !((BackStackRecord)records.get(reorderingEnd)).mReorderingAllowed) {
++reorderingEnd;
}
}
this.executeOpsTogether(records, isRecordPop, recordNum, reorderingEnd);
startIndex = reorderingEnd;
recordNum = reorderingEnd - 1;
}
}
if (startIndex != numRecords) {
this.executeOpsTogether(records, isRecordPop, startIndex, numRecords);
}
} else {
throw new IllegalStateException("Internal error with the back stack records");
}
}
}
private void executeOpsTogether(ArrayList<BackStackRecord> records, ArrayList<Boolean> isRecordPop, int startIndex, int endIndex) {
boolean allowReordering = ((BackStackRecord)records.get(startIndex)).mReorderingAllowed;
boolean addToBackStack = false;
if (this.mTmpAddedFragments == null) {
this.mTmpAddedFragments = new ArrayList();
} else {
this.mTmpAddedFragments.clear();
}
this.mTmpAddedFragments.addAll(this.mAdded);
Fragment oldPrimaryNav = this.getPrimaryNavigationFragment();
int postponeIndex;
for(postponeIndex = startIndex; postponeIndex < endIndex; ++postponeIndex) {
BackStackRecord record = (BackStackRecord)records.get(postponeIndex);
boolean isPop = (Boolean)isRecordPop.get(postponeIndex);
// 對mOps進行優化,add或者remove(mOps即第三部分提到的保存add進的fragmnet集合)
if (!isPop) {
// 在28以前這裏會執行 expandReplaceOps 方法把 replace 替換(目標 fragment 已經被 add )成相應的 remove 和 add 兩個操做,或者(目標 fragment 沒有被 add )只替換成 add 操做。
oldPrimaryNav = record.expandOps(this.mTmpAddedFragments, oldPrimaryNav);
} else {
oldPrimaryNav = record.trackAddedFragmentsInPop(this.mTmpAddedFragments, oldPrimaryNav);
}
addToBackStack = addToBackStack || record.mAddToBackStack;
}
this.mTmpAddedFragments.clear();
if (!allowReordering) {
FragmentTransition.startTransitions(this, records, isRecordPop, startIndex, endIndex, false);
}
// 若是allowReordering爲true,則此方法後面會走不通,則會走下面的判斷,最終都會到達咱們這部分最重要的方法————moveToState
executeOps(records, isRecordPop, startIndex, endIndex);
postponeIndex = endIndex;
if (allowReordering) {
/**
* allowReordering爲true,走此邏輯
* 容許從新排序(須要本身調用FragmentTransaction.setReorderingAllowed()方法設置)
* 必須啓用fragment事務中的從新排序(即allowReordering),才能
* 使延遲的fragment過渡生效,具體用法請參考:https://www.jianshu.com/p/232073710172
*/
ArraySet<Fragment> addedFragments = new ArraySet();
this.addAddedFragments(addedFragments);
// 此方法最後會走到moveToState方法,具體源碼請自行查看
postponeIndex = this.postponePostponableTransactions(records, isRecordPop, startIndex, endIndex, addedFragments);
this.makeRemovedFragmentsInvisible(addedFragments);
}
...
}
private static void executeOps(ArrayList<BackStackRecord> records, ArrayList<Boolean> isRecordPop, int startIndex, int endIndex) {
for(int i = startIndex; i < endIndex; ++i) {
BackStackRecord record = (BackStackRecord)records.get(i);
boolean isPop = (Boolean)isRecordPop.get(i);
// 從上面分析可知isRecordPop取出來的是false(「回退棧」出棧時爲true)
if (isPop) {
record.bumpBackStackNesting(-1);
boolean moveToState = i == endIndex - 1;
// 若爲回退棧出棧操做,則執行此方法,
// 此方法中根據op.cmd判斷對framgnet進行相應的處理,
// 與else分支相同的cmd指令處理邏輯不一樣
record.executePopOps(moveToState);
} else {
record.bumpBackStackNesting(1);
record.executeOps();
}
}
}
複製代碼
咱們從removeRedundantOperationsAndExecute()方法的源碼中能夠看到該方法其實是對records集合中全部動做的startIndex(起始動做位置), recordNum(須要操做的動做個數)的設置,而後都會去調用executeOpsTogether()方法,而executeOpsTogether()方法咱們只展現部分代碼,其中會對mOps進行擴展操做,最後調用方法executeOps()繼續操做,而方法executeOps中又通過判斷最終調用BackStackRecord類的executeOps()方法。
// BackStackRecord類:
void executeOps() {
int numOps = this.mOps.size();
// 遍歷執行全部的mOps(包含咱們commit操做前的全部其它操做,好比:add、hide等)
for(int opNum = 0; opNum < numOps; ++opNum) {
BackStackRecord.Op op = (BackStackRecord.Op)this.mOps.get(opNum);
Fragment f = op.fragment;
if (f != null) {
f.setNextTransition(this.mTransition, this.mTransitionStyle);
}
// 根據op.cmd指令進行操做,相信根據下面每一個分支的邏輯能分別出每一個指令對應的操做
switch(op.cmd) {
case 1:
f.setNextAnim(op.enterAnim);
this.mManager.addFragment(f, false);
break;
case 2:
default:
throw new IllegalArgumentException("Unknown cmd: " + op.cmd);
case 3:
f.setNextAnim(op.exitAnim);
this.mManager.removeFragment(f);
break;
case 4:
f.setNextAnim(op.exitAnim);
this.mManager.hideFragment(f);
break;
case 5:
f.setNextAnim(op.enterAnim);
this.mManager.showFragment(f);
break;
case 6:
f.setNextAnim(op.exitAnim);
this.mManager.detachFragment(f);
break;
case 7:
f.setNextAnim(op.enterAnim);
this.mManager.attachFragment(f);
break;
case 8:
this.mManager.setPrimaryNavigationFragment(f);
break;
case 9:
this.mManager.setPrimaryNavigationFragment((Fragment)null);
}
if (!this.mReorderingAllowed && op.cmd != 1 && f != null) {
this.mManager.moveFragmentToExpectedState(f);
}
}
// 只有沒設置setReorderingAllowed(true)的才能繼續,
// 而設置的會在前面的某步邏輯當中走到moveToState方法內,上面有說明
if (!this.mReorderingAllowed) {
// 最後調用咱們這部分最重要的方法:moveToState
this.mManager.moveToState(this.mManager.mCurState, true);
}
}
// 1. 提交add操做時將當前提交的fragmen添加進mActive和mAdded裏
// 並重置fragment.mAdded和fragment.mRemoving兩個的狀態
public void addFragment(Fragment fragment, boolean moveToStateNow) {
if (DEBUG) {
Log.v("FragmentManager", "add: " + fragment);
}
// 調用makeActive,將fragment添加進mActive
this.makeActive(fragment);
if (!fragment.mDetached) {
if (this.mAdded.contains(fragment)) {
throw new IllegalStateException("Fragment already added: " + fragment);
}
synchronized(this.mAdded) {
// 將fragment也添加進mAdded裏
this.mAdded.add(fragment);
}
// 設置mAdded和mRemoving狀態
fragment.mAdded = true;
fragment.mRemoving = false;
if (fragment.mView == null) {
fragment.mHiddenChanged = false;
}
if (fragment.mHasMenu && fragment.mMenuVisible) {
this.mNeedMenuInvalidate = true;
}
if (moveToStateNow) {
this.moveToState(fragment);
}
}
}
void makeActive(Fragment f) {
if (f.mIndex < 0) {
f.setIndex(this.mNextFragmentIndex++, this.mParent);
if (this.mActive == null) {
this.mActive = new SparseArray();
}
// 將fragment添加進mActive
this.mActive.put(f.mIndex, f);
if (DEBUG) {
Log.v("FragmentManager", "Allocated fragment index " + f);
}
}
}
// 2. 提交remove操做時將當前提交的fragment從mAdded移除
// 並重置fragment.mAdded和fragment.mRemoving兩個的狀態
public void removeFragment(Fragment fragment) {
if (DEBUG) {
Log.v("FragmentManager", "remove: " + fragment + " nesting=" + fragment.mBackStackNesting);
}
boolean inactive = !fragment.isInBackStack();
if (!fragment.mDetached || inactive) {
synchronized(this.mAdded) {
this.mAdded.remove(fragment);
}
if (fragment.mHasMenu && fragment.mMenuVisible) {
this.mNeedMenuInvalidate = true;
}
fragment.mAdded = false;
fragment.mRemoving = true;
}
}
// 3. 設置fragment.mHidden的狀態爲false
public void showFragment(Fragment fragment) {
if (DEBUG) {
Log.v("FragmentManager", "show: " + fragment);
}
if (fragment.mHidden) {
fragment.mHidden = false;
fragment.mHiddenChanged = !fragment.mHiddenChanged;
}
}
// 4. 設置fragment.mHidden的狀態爲true
public void hideFragment(Fragment fragment) {
if (DEBUG) {
Log.v("FragmentManager", "hide: " + fragment);
}
if (!fragment.mHidden) {
fragment.mHidden = true;
fragment.mHiddenChanged = !fragment.mHiddenChanged;
}
}
複製代碼
哈哈,這段代碼彷佛有點多,不過好理解,咱們來先說一下這段代碼裏都有些什麼,咱們從executeOps()方法中能夠看到該方法裏經過for循環對mOps進行了遍歷,而這次遍歷會對咱們本次commit提交的全部操做進行設置。好比咱們上面列出的四中操做:add、remove、show和hide同樣。
咱們先來看這段代碼中的兩個集合:mAdded和mActive
mAdded:包含了全部已經 added 而且沒有被從Activity中removed和detached的Fragments
注:若是一個 Fragment被添加到Activity中那麼這個Fragment會被added到該列表。Fragment被從Activity中removed或者Fragment從Activity中detached,則就會被從該列表中移除。
mAdded 的一個超集,是綁定到一個 Activity 上的全部 Fragment。包括返回棧中全部的經過任何 FragmentTransaction 添加的 Fragments。這是很是重要的由於以下緣由:
當一個 Activity 要保存它的 State 時,它必須保存它全部 Fragment 的狀態,由於 mActive 保存了全部 Fragment,因此係統只要存儲這個列表裏的 Fragment 的狀態就行了。而mAdded 只是被序列化成一個整形數組,每一個元素指向 Fragment 在 mActive 中的下標位置(這塊在前面 Fragment 的存儲與恢復中分析到了)。
在恢復 Activity 的狀態時,FragmentManager 的狀態也會被恢復,mActive 列表就能夠被用來恢復 mAdded 列表,由於保存狀態的時候mAdded 被簡單的保存爲整形數組。
當一個 Activity 經歷它的各生命週期時,它必須引發全部綁定的 Fragment 經歷各自的生命週期。
它持有全部 BackStack 返回棧引用的對象。
注:若是一個Fragment被添加到Activity中那麼這個Fragment會被added到該列表。只有在兩種狀況 Fragment纔會被從該列表中移除:一是,Fragment被從Activity中移除而且沒有在返回棧中;二是一個transaction從返回棧中被pop出來、Fragment的add或者replace操做被逆向,即返回棧再也不持有 Fragment。
咱們接着來講moveToState這個方法:
// FragmentManagerImpl類:
void moveToState(int newState, boolean always) {
if (this.mHost == null && newState != 0) {
throw new IllegalStateException("No activity");
} else if (always || newState != this.mCurState) {
this.mCurState = newState;
if (this.mActive != null) {
int numAdded = this.mAdded.size();
int numActive;
// 遍歷mAdded集合,確定會走此代碼邏輯
for(numActive = 0; numActive < numAdded; ++numActive) {
Fragment f = (Fragment)this.mAdded.get(numActive);
// 將fragment移至預期狀態
this.moveFragmentToExpectedState(f);
}
numActive = this.mActive.size();
// // 遍歷mActive集合(若調用回退棧出棧,則會走此出代碼)
for(int i = 0; i < numActive; ++i) {
Fragment f = (Fragment)this.mActive.valueAt(i);
// 當前framgnet不爲空 而且 此時操做爲remove或者detach 而且不是新添加的則會執行下面代碼
if (f != null && (f.mRemoving || f.mDetached) && !f.mIsNewlyAdded) {
// // 將fragment移至預期狀態
this.moveFragmentToExpectedState(f);
}
}
// fragment的成員屬性f.mDeferStart爲true才能走通下面代碼(具體暫不分析)
this.startPendingDeferredFragments();
if (this.mNeedMenuInvalidate && this.mHost != null && this.mCurState == 4) {
this.mHost.onSupportInvalidateOptionsMenu();
this.mNeedMenuInvalidate = false;
}
}
}
}
複製代碼
咱們來看一下moveToState方法中的參數newState,BackStackRecord類中的executeOps裏傳過來的是mManager.mCurState,而mManager.mCurState默認爲0,即須要add的狀態。咱們如今回想一下fragment爲何會隨着Activity的週期變化而變化呢?咱們來看段代碼:
// FragmentActivity類:
protected void onCreate(@Nullable Bundle savedInstanceState) {
this.mFragments.attachHost((Fragment)null);
super.onCreate(savedInstanceState);
......
this.mFragments.dispatchCreate();
}
// FragmentController類:
public void dispatchCreate() {
this.mHost.mFragmentManager.dispatchCreate();
}
// FragmentManagerImpl類:
public void dispatchCreate() {
this.mStateSaved = false;
this.mStopped = false;
this.dispatchStateChange(1);
}
private void dispatchStateChange(int nextState) {
try {
this.mExecutingActions = true;
// 這裏走到了moveToState
this.moveToState(nextState, false);
} finally {
this.mExecutingActions = false;
}
this.execPendingActions();
}
複製代碼
這段代碼是從上到下的順序執行的,咱們能夠看到在FragmentActivity的onCreate週期方法中一步一步的走到了moveToState,而moveToState正是走到fragment週期方法的關鍵(FragmentActivity的其它週期方法同onCreate方法也會走到對應的fragment的週期方法中)。既然moveToState是走到fragment週期方法的關鍵,那咱們繼續往下分析,上面已經說到會走到FragmentManagerImpl類的moveFragmentToExpectedState(f)方法中:
// FragmentManagerImpl類:
void moveFragmentToExpectedState(Fragment f) {
if (f != null) {
int nextState = this.mCurState;
if (f.mRemoving) {
// 若是操做爲remove則nextState設置爲1或者0,用於後面判斷
if (f.isInBackStack()) {
nextState = Math.min(nextState, 1);
} else {
nextState = Math.min(nextState, 0);
}
}
// 繼續走同名方法
this.moveToState(f, nextState, f.getNextTransition(), f.getNextTransitionStyle(), false);
// 若是當前View不爲空,則添加布局執行動畫
if (f.mView != null) {
Fragment underFragment = this.findFragmentUnder(f);
if (underFragment != null) {
View underView = underFragment.mView;
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) {
if (f.mPostponedAlpha > 0.0F) {
f.mView.setAlpha(f.mPostponedAlpha);
}
f.mPostponedAlpha = 0.0F;
f.mIsNewlyAdded = false;
FragmentManagerImpl.AnimationOrAnimator anim = this.loadAnimation(f, f.getNextTransition(), true, f.getNextTransitionStyle());
if (anim != null) {
setHWLayerAnimListenerIfAlpha(f.mView, anim);
if (anim.animation != null) {
f.mView.startAnimation(anim.animation);
} else {
anim.animator.setTarget(f.mView);
anim.animator.start();
}
}
}
}
if (f.mHiddenChanged) {
// 完成顯示隱藏fragment
this.completeShowHideFragment(f);
}
}
}
void moveToState(Fragment f, int newState, int transit, int transitionStyle, boolean keepActive) {
// 從新判斷設置newState狀態值
if ((!f.mAdded || f.mDetached) && newState > 1) {
newState = 1;
}
if (f.mRemoving && newState > f.mState) {
if (f.mState == 0 && f.isInBackStack()) {
newState = 1;
} else {
newState = f.mState;
}
}
if (f.mDeferStart && f.mState < 3 && newState > 2) {
newState = 2;
}
// 若是fragment自身的狀態<=newState狀態,則證實此時fragment是被建立階段
if (f.mState <= newState) {
label297: {
if (f.mFromLayout && !f.mInLayout) {
return;
}
if (f.getAnimatingAway() != null || f.getAnimator() != null) {
f.setAnimatingAway((View)null);
f.setAnimator((Animator)null);
this.moveToState(f, f.getStateAfterAnimating(), 0, 0, true);
}
// 判斷fragment狀態進行處理
switch(f.mState) {
case 0:
if (newState > 0) {
if (DEBUG) {
Log.v("FragmentManager", "moveto CREATED: " + f);
}
if (f.mSavedFragmentState != null) {
f.mSavedFragmentState.setClassLoader(this.mHost.getContext().getClassLoader());
f.mSavedViewState = f.mSavedFragmentState.getSparseParcelableArray("android:view_state");
f.mTarget = this.getFragment(f.mSavedFragmentState, "android:target_state");
if (f.mTarget != null) {
f.mTargetRequestCode = f.mSavedFragmentState.getInt("android:target_req_state", 0);
}
if (f.mSavedUserVisibleHint != null) {
f.mUserVisibleHint = f.mSavedUserVisibleHint;
f.mSavedUserVisibleHint = null;
} else {
f.mUserVisibleHint = f.mSavedFragmentState.getBoolean("android:user_visible_hint", true);
}
if (!f.mUserVisibleHint) {
f.mDeferStart = true;
if (newState > 2) {
newState = 2;
}
}
}
f.mHost = this.mHost;
f.mParentFragment = this.mParent;
f.mFragmentManager = this.mParent != null ? this.mParent.mChildFragmentManager : this.mHost.getFragmentManagerImpl();
if (f.mTarget != null) {
if (this.mActive.get(f.mTarget.mIndex) != f.mTarget) {
throw new IllegalStateException("Fragment " + f + " declared target fragment " + f.mTarget + " that does not belong to this FragmentManager!");
}
if (f.mTarget.mState < 1) {
this.moveToState(f.mTarget, 1, 0, 0, true);
}
}
this.dispatchOnFragmentPreAttached(f, this.mHost.getContext(), false);
f.mCalled = false;
// 執行fragment的onAttach週期方法
f.onAttach(this.mHost.getContext());
if (!f.mCalled) {
throw new SuperNotCalledException("Fragment " + f + " did not call through to super.onAttach()");
}
if (f.mParentFragment == null) {
this.mHost.onAttachFragment(f);
} else {
f.mParentFragment.onAttachFragment(f);
}
this.dispatchOnFragmentAttached(f, this.mHost.getContext(), false);
if (!f.mIsCreated) {
this.dispatchOnFragmentPreCreated(f, f.mSavedFragmentState, false);
f.performCreate(f.mSavedFragmentState);
this.dispatchOnFragmentCreated(f, f.mSavedFragmentState, false);
} else {
f.restoreChildFragmentState(f.mSavedFragmentState);
f.mState = 1;
}
f.mRetaining = false;
}
case 1:
this.ensureInflatedFragmentView(f);
if (newState > 1) {
if (DEBUG) {
Log.v("FragmentManager", "moveto ACTIVITY_CREATED: " + f);
}
if (!f.mFromLayout) {
ViewGroup container = null;
if (f.mContainerId != 0) {
if (f.mContainerId == -1) {
this.throwException(new IllegalArgumentException("Cannot create fragment " + f + " for a container view with no id"));
}
container = (ViewGroup)this.mContainer.onFindViewById(f.mContainerId);
if (container == null && !f.mRestored) {
String resName;
try {
resName = f.getResources().getResourceName(f.mContainerId);
} catch (NotFoundException var9) {
resName = "unknown";
}
this.throwException(new IllegalArgumentException("No view found for id 0x" + Integer.toHexString(f.mContainerId) + " (" + resName + ") for fragment " + f));
}
}
f.mContainer = container;
// 執行fragment的onCreateView週期方法 f.performCreateView(f.performGetLayoutInflater(f.mSavedFragmentState), container, f.mSavedFragmentState);
if (f.mView == null) {
f.mInnerView = null;
} else {
f.mInnerView = f.mView;
f.mView.setSaveFromParentEnabled(false);
if (container != null) {
container.addView(f.mView);
}
if (f.mHidden) {
f.mView.setVisibility(8);
}
// 執行fragment的onViewCreated週期方法
f.onViewCreated(f.mView, f.mSavedFragmentState);
this.dispatchOnFragmentViewCreated(f, f.mView, f.mSavedFragmentState, false);
f.mIsNewlyAdded = f.mView.getVisibility() == 0 && f.mContainer != null;
}
}
f.performActivityCreated(f.mSavedFragmentState);
this.dispatchOnFragmentActivityCreated(f, f.mSavedFragmentState, false);
if (f.mView != null) {
f.restoreViewState(f.mSavedFragmentState);
}
// 執行fragment的onActivityCreated週期方法
f.mSavedFragmentState = null;
}
case 2:
if (newState > 2) {
if (DEBUG) {
Log.v("FragmentManager", "moveto STARTED: " + f);
}
// 執行framgnet的onStart週期方法
f.performStart();
this.dispatchOnFragmentStarted(f, false);
}
case 3:
break;
default:
break label297;
}
if (newState > 3) {
if (DEBUG) {
Log.v("FragmentManager", "moveto RESUMED: " + f);
}
// 執行framgnet的onResume週期方法
f.performResume();
this.dispatchOnFragmentResumed(f, false);
f.mSavedFragmentState = null;
f.mSavedViewState = null;
}
}
// 若是fragment自身的狀態>=newState狀態,則證實此時fragment是被銷燬階段
} else if (f.mState > newState) {
switch(f.mState) {
case 4:
if (newState < 4) {
if (DEBUG) {
Log.v("FragmentManager", "movefrom RESUMED: " + f);
}
// 執行framgnet的onPause週期方法
f.performPause();
this.dispatchOnFragmentPaused(f, false);
}
case 3:
if (newState < 3) {
if (DEBUG) {
Log.v("FragmentManager", "movefrom STARTED: " + f);
}
// 執行framgnet的onStop週期方法
f.performStop();
this.dispatchOnFragmentStopped(f, false);
}
case 2:
if (newState < 2) {
if (DEBUG) {
Log.v("FragmentManager", "movefrom ACTIVITY_CREATED: " + f);
}
if (f.mView != null && this.mHost.onShouldSaveFragmentState(f) && f.mSavedViewState == null) {
this.saveFragmentViewState(f);
}
// 執行framgnet的onDestroyView週期方法
f.performDestroyView();
this.dispatchOnFragmentViewDestroyed(f, false);
if (f.mView != null && f.mContainer != null) {
f.mContainer.endViewTransition(f.mView);
f.mView.clearAnimation();
FragmentManagerImpl.AnimationOrAnimator anim = null;
if (this.mCurState > 0 && !this.mDestroyed && f.mView.getVisibility() == 0 && f.mPostponedAlpha >= 0.0F) {
anim = this.loadAnimation(f, transit, false, transitionStyle);
}
f.mPostponedAlpha = 0.0F;
if (anim != null) {
this.animateRemoveFragment(f, anim, newState);
}
f.mContainer.removeView(f.mView);
}
f.mContainer = null;
f.mView = null;
f.mViewLifecycleOwner = null;
f.mViewLifecycleOwnerLiveData.setValue((Object)null);
f.mInnerView = null;
f.mInLayout = false;
}
case 1:
if (newState < 1) {
if (this.mDestroyed) {
if (f.getAnimatingAway() != null) {
View v = f.getAnimatingAway();
f.setAnimatingAway((View)null);
v.clearAnimation();
} else if (f.getAnimator() != null) {
Animator animator = f.getAnimator();
f.setAnimator((Animator)null);
animator.cancel();
}
}
if (f.getAnimatingAway() == null && f.getAnimator() == null) {
if (DEBUG) {
Log.v("FragmentManager", "movefrom CREATED: " + f);
}
if (!f.mRetaining) {
// 執行framgnet的onDestroy週期方法
f.performDestroy();
this.dispatchOnFragmentDestroyed(f, false);
} else {
f.mState = 0;
}
// 執行framgnet的onDetach週期方法
f.performDetach();
this.dispatchOnFragmentDetached(f, false);
if (!keepActive) {
if (!f.mRetaining) {
this.makeInactive(f);
} else {
f.mHost = null;
f.mParentFragment = null;
f.mFragmentManager = null;
}
}
} else {
f.setStateAfterAnimating(newState);
newState = 1;
}
}
}
}
if (f.mState != newState) {
Log.w("FragmentManager", "moveToState: Fragment state for " + f + " not updated inline; " + "expected state " + newState + " found " + f.mState);
f.mState = newState;
}
}
複製代碼
繼續從FragmentManagerImpl類的moveFragmentToExpectedState(f)方法中提及,該方法中又會繼續調用moveToState方法,這個方法和上面的moveToState方法不一樣,這倆方法是同名不一樣參的方法,該方法中會根據fragment的mState自身的狀態值和newState傳過來的狀態值進行比較來區分:當前fragment是走建立階段的週期方法仍是銷燬階段的週期方法,進一步再經過fragment的mState判斷到底要走哪一個fragment的週期方法,具體標註可看代碼註釋哦。
Fragment的7種狀態(mState):
至此咱們的Fragment的源碼分析按照一開始的流程已分析完畢。
咱們最後說一下回退棧(FragmentManagerImpl的成員mBackStack),其實咱們在cooimt操做時咱們就已經設置了「回退棧」內的元素。從新看一下該部分代碼:
// FragmentManagerImpl類:
public boolean generateOps(ArrayList<BackStackRecord> records, ArrayList<Boolean> isRecordPop) {
if (FragmentManagerImpl.DEBUG) {
Log.v("FragmentManager", "Run: " + this);
}
records.add(this);
isRecordPop.add(false);
if (this.mAddToBackStack) {
this.mManager.addBackStackState(this);
}
return true;
}
void addBackStackState(BackStackRecord state) {
if (this.mBackStack == null) {
this.mBackStack = new ArrayList();
}
this.mBackStack.add(state);
}
複製代碼
咱們回顧一下上面的邏輯,在執行BackStackRecord類(實現了OpGenerator接口)的方法generateOps時,就已經將當前的BackStackRecord入棧啦。而BackStackRecord出棧主要是調用以下幾個方法:
PopBackStackState類 實現了 OpGenerator 接口,具體實現以下:
若咱們本身主動調用popBackStack兩個方法之一,實際上就是調用了enqueueAction方法,並傳入PopBackStackState類的新建立實例,而此時isRecordPop集合裏存的值就是true。在上面部分分析中也說明了isRecordPop集合中存的元素對代碼邏輯的影響。最後會致使界面顯示的是上一個fragment視圖。
若是 回退棧 mBackStack 爲空就終止出棧操做並返回 false,當name == null && id < 0 && (flags & POP_BACK_STACK_INCLUSIVE) == 0 (調用的是popBackStack()方法)時,把返回棧最後一個 BackStackRecord出棧。當 name 或者 id 被指定的時候,倒序遍歷 mBackStack ,若是遇到 name 或者 id 相符就退出循環,此時 index 爲第一次匹配到的下標,若是flags==POP_BACK_STACK_INCLUSIVE 繼續遍歷返回棧,直至棧底或者遇到不匹配的跳出循環。最後出棧全部 BackStackRecord。
參考連接:
注:如有什麼地方闡述有誤,敬請指正。