Fragment源码分析分两部分:
使用刨坑
commitXXX和popXXX
前言
接着上一篇继续将fragment的提交过程,为啥单独将提交过程呢,因为它复杂嘛。。。
- commit过程和pop过程其实是一样的,支持生成backStackState一个生成popBackStackState。
- add、remove、show、hide、replece过程其实也是一样的,只是对应的标志位不同
- show就是将view设置为visible,hide就是Gone,replace:如果有了,先remove在add,如果没有直接add
- 情况捏就是这么个情况
首先引入一段代码,因为使用了addToBackStack,因此不能用带now的commit
FragmentTransaction transaction = manager.beginTransaction();
transaction.add(R.id.fragment_one, new FirstFragment(R.layout.fragment_first), "firstFragment");
transaction.addToBackStack("fragment_one");
transaction.commit();
commitXXX()提交过程:
我们知道,commitXXX之前的操作都是做个记录,虚晃一枪,真正执行的操作是commitXXX();提交方法一共有四个,上一篇我们粗略介绍了其中的差别,现在我们详细讲一下:
注意:这里的disallowAddToBackStack()和上一节将的addToBackStack是相矛盾的,同时设置会相互报错,二者必然选其一,因此只要有Now,就不能加入backStack;
@Override
public int commit() {
return commitInternal(false);
}
@Override
public int commitAllowingStateLoss() {
return commitInternal(true);
}
@Override
public void commitNow() {
disallowAddToBackStack();
mManager.execSingleAction(this, false);
}
@Override
public void commitNowAllowingStateLoss() {
disallowAddToBackStack();
mManager.execSingleAction(this, true);
}
popBackStackXXX()提交过程:
弹出一共有6种:
- 空参就是一次pop操作弹出一个栈顶的fragment的元素
- name就是一次弹出name以及name以上的fragment的元素
- id就是一次弹出id以及id以上的元素
- 就那么简单
public abstract void popBackStack();
public abstract boolean popBackStackImmediate();
public abstract void popBackStack(@Nullable String name, int flags);
public abstract boolean popBackStackImmediate(@Nullable String name, int flags);
public abstract void popBackStack(int id, int flags);
public abstract boolean popBackStackImmediate(int id, int flags);
(一)执行提交前的准备工作
有now和没有now的区别就是能否添加回退栈,这里由于篇幅原因,commit的一些前奏我就总结一下吧:
- 四种commit()都不能重复提交,不然报错:没有now的报重复提交,有now的报重复添加fragment
- 没有AllowingStateLoss的commit()会判断当前的activity是否执行onStop或者onSaveInstanceState,否则报错:不能在onSaveInstanceState之后提交。有的话直接return结束本地提交操作
- 如果addToBackStack,有now的会报错,没有now的会给mBackStack集合进行装箱操作。
- 没有now的会将recorder装箱到mPendingActions中去,等待handler的消息分发执行;
- 没有now的从execPendingActions()方法开始执行,有now的从execSingleAction开始执行。
提交方式 | mPendingActions | addToBackStack | checkStateLoss |
---|---|---|---|
commit | 装箱 | 能加,装箱mBackStack | 报错 |
commitNow | 不装箱 | 不能,没有mBackStack | 报错 |
commitA | 装箱 | 能加,装箱mBackStack | 丢弃 |
commitNowA | 不装 | 不能,没有mBackStac | 丢弃 |
checkStateLoss就是第二点;
(二)执行动作
过程很长,我就挑重点的讲解,不然怕你们看不下去;
因为commit是最复杂的,我们从execPendingActions()方法开始讲解。
不论哪种提交方式,都是这么三步:
- 一、用来判断是否丢弃本次提交;二、生成mTmpRecords、mTmpIsPop两个数组集合
- 给mTmpRecords、mTmpIsPop以及mBackStack进行装箱
- 第三步重点讲解
public boolean execPendingActions() {
ensureExecReady(true); (1)
boolean didSomething = false;
while (generateOpsForPendingActions(mTmpRecords, mTmpIsPop)) { (2)
-----------------generateOpsForPendingActions的作用---------------------------
records.add(this); //this指的是BackStackRecord
isRecordPop.add(false); //因为commit所以是false,如果是pop那么就是true
if (mAddToBackStack) {
mManager.addBackStackState(this);//如果有addToBackStack那么就装箱mBackStack集合
}
------------------------------------------------------------------
mExecutingActions = true;
try {
removeRedundantOperationsAndExecute(mTmpRecords, mTmpIsPop);(3)
} finally {
cleanupExec();
}
didSomething = true;
}
updateOnBackPressedCallbackEnabled(); //设置返回键
doPendingDeferredStart();
burpActive();
return didSomething;
}
(三)开始执行
private void removeRedundantOperationsAndExecute(ArrayList<BackStackRecord> records,
ArrayList<Boolean> isRecordPop) {
.................日常判空......................
......重点是executeOpsTogether方法:recordNum = 0;reorderingEnd = 1;........
executeOpsTogether(records, isRecordPop, recordNum, reorderingEnd);
................
}
1. startTransitions开始事务
2. executeOps执行ops操作
private void executeOpsTogether(ArrayList<BackStackRecord> records,ArrayList<Boolean> isRecordPop, int startIndex, int endIndex) {
final boolean allowReordering = records.get(startIndex).mReorderingAllowed;
boolean addToBackStack = false;
addToBackStack = addToBackStack || record.mAddToBackStack; // 有回退栈
................................
if (!allowReordering) {
FragmentTransition.startTransitions(this, records, isRecordPop, startIndex, endIndex,false); (1)
}
executeOps(records, isRecordPop, startIndex, endIndex); (2)
................................
}
(3-1)startTransitions开始事务
FragmentTransition.java
static void startTransitions(FragmentManagerImpl fragmentManager,ArrayList<BackStackRecord> records, ArrayList<Boolean> isRecordPop,int startIndex, int endIndex, boolean isReordered) {
SparseArray<FragmentContainerTransition> transitioningFragments =
new SparseArray<>();
...........................简化省略,看这句话就行了..............................
calculateFragments(record, transitioningFragments, isReordered);
----------------------------调用方法---------------------------------
//这个方法中给transitioningFragments、mActive集合进行装箱,然后调用moveToState方法
addToFirstInLastOut(transaction, op, transitioningFragments, false, isReordered);
----------------------------调用方法---------------------------------
//这个是核心方法,详细见(3-1-1)
manager.moveToState(fragment, Fragment.CREATED, 0, 0, false);
----------------------------end-------------------------------------------
...........................简化省略.............................
}
(3-1-1)核心方法moveToState()方法
该方法是fragment的最最核心的方法,说白了就是生命周期的调度过程,总结一下:
commitXXX到onResume():结束
popbackStackXXX到onDetach():结束
........源码太长影响美观,看上面的图就行了........
#2
(3-2)executeOps执行ops操作
执行什么呢,当然是fragment动画,以及add、remove、hide、show、等一系列操作了;但是这些操作也只是在fragment中的对应的属性字段进行修改,如fragment.mAdded = true;然后操作mAdded集合。
这里最终还是调用了(3-1-1)的5个参数的moveToState方法,继续执行刚才的onCreate操作
private static void executeOps(ArrayList<BackStackRecord> records,ArrayList<Boolean> isRecordPop, int startIndex, int endIndex) {
..............简化省略,主要看这句....................
record.executeOps();
}
//这个方法就是用来给fragment加载动画,并执行fragment的add、remove、hide、show、等一系列操作的;
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);
mManager.addFragment(f, false);
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.showFragment(f);
break;
case OP_DETACH:
f.setNextAnim(op.mExitAnim);
mManager.detachFragment(f);
break;
case OP_ATTACH:
f.setNextAnim(op.mEnterAnim);
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;
}
if (!mReorderingAllowed && op.mCmd != OP_ADD && f != null) {
mManager.moveFragmentToExpectedState(f);
}
}
if (!mReorderingAllowed) {
//这里最终还是调用了(3-1-1)的5个参数的moveToState方法,继续执行刚才的onCreate操作
mManager.moveToState(mManager.mCurState, true);
}
}