整体流程
在上一篇文章从activity和fragment自身这两个视角分析了一下fragment生命周期流程,感兴趣的小伙伴可以去看一下从源码角度分析fragment生命周期流程,在这里附上一个add的流程图看起来更加直观,在里面也会提到哪些步骤add和replace是不一样的
add和replace
add和replace在源码中主要的不同点提现在
- 肯定是add和replace最初的op.mCmd值是不一样的一个是OP_ADD一个是OP_REPLACE
- record.expandOps方法中replace是会把OP_REPLACE拆分成OP_REMOVE和OP_ADD然后循环执行fragmentStateManager.moveToExpectedState();不同之处就在这里,replace多了一个remove操作,它会把之前的fragment移出去,至于被移出的fragment的生命周期走到onDestroyView还是onDetach看它的事务是否被加入了返回栈,具体看第三点
- computeExpectedState方法获取的期望生命周期不一样
// fragmentStateManager
int computeExpectedState() {
//mFragmentManagerState的值来源于创建fragmentStateManager的时候,把fragmentManager的生命周期赋值给它
int maxState = mFragmentManagerState;
//这个是和fragmentTransaction.setMaxLifecycle配合使用的,这里没用到,默认是RESUMED
switch (mFragment.mMaxState) {
case RESUMED:
// maxState can't go any higher than RESUMED, so there's nothing to do here
break;
case STARTED:
maxState = Math.min(maxState, Fragment.STARTED);
break;
case CREATED:
maxState = Math.min(maxState, Fragment.CREATED);
break;
case INITIALIZED:
maxState = Math.min(maxState, Fragment.ATTACHED);
break;
default:
maxState = Math.min(maxState, Fragment.INITIALIZING);
}
//这里貌似是判断是否在xml中引入的fragment
if (mFragment.mFromLayout) {
if (mFragment.mInLayout) {
// Move them immediately to VIEW_CREATED when they are
// actually added to the layout (mInLayout).
maxState = Math.max(mFragmentManagerState, Fragment.VIEW_CREATED);
// But don't move to higher than VIEW_CREATED until the view is added to its parent
// and the LayoutInflater call has returned
if (mFragment.mView != null && mFragment.mView.getParent() == null) {
maxState = Math.min(maxState, Fragment.VIEW_CREATED);
}
} else {
if (mFragmentManagerState < Fragment.ACTIVITY_CREATED) {
// But while they are not in the layout, don't allow their
// state to progress upward until the FragmentManager state
// is at least ACTIVITY_CREATED. This ensures they get the onInflate()
// callback before being attached or created.
maxState = Math.min(maxState, mFragment.mState);
} else {
// Once the FragmentManager state is at least ACTIVITY_CREATED
// their state can progress up to CREATED as we assume that
// they are not ever going to be in layout
maxState = Math.min(maxState, Fragment.CREATED);
}
}
}
//如果是add提交事务的话就走不进该判断,而replace由于被拆分成remove和add
//remove操作在executeOps方法removeFragment的时候就置为false了
//因此此时add操作:maxState==RESUMED,remove操作:masState==CREATED
if (!mFragment.mAdded) {
maxState = Math.min(maxState, Fragment.CREATED);
}
if (awaitingEffect == SpecialEffectsController.Operation.LifecycleImpact.ADDING) {
// Fragments awaiting their enter effects cannot proceed beyond that state
maxState = Math.min(maxState, Fragment.AWAITING_ENTER_EFFECTS);
} else if (awaitingEffect == SpecialEffectsController.Operation.LifecycleImpact.REMOVING) {
// Fragments that are in the process of being removed shouldn't go below that state
maxState = Math.max(maxState, Fragment.AWAITING_EXIT_EFFECTS);
}
//这里也是同样的道理executeOps方法removeFragment的时候mRemoving会被置为true
else if (mFragment.mRemoving) {
//被replace的fragment是否加入了返回栈,加入了maxState==CREATED,否则为INITIALIZING
if (mFragment.isInBackStack()) {
// Fragments on the back stack shouldn't go higher than CREATED
maxState = Math.min(maxState, Fragment.CREATED);
} else {
// While removing a fragment, we always move to INITIALIZING
maxState = Math.min(maxState, Fragment.INITIALIZING);
}
}
return maxState;
}
//moveToExpectedState方法
//通过上面可以知道remove操作得到的期望的生命周期肯定小于当前的生命周期状态,这个时候和add就是完全想反的操作了
//以下代码解释了为什么加入返回栈的只会走到onDestroyView,而未加入的会走detach
case Fragment.CREATED:
destroyFragmentView();
mFragment.mState = Fragment.CREATED;
break;
case Fragment.ATTACHED:
destroy();
break;
case Fragment.INITIALIZING:
detach();
break;
fragment返回栈
addToBackStack做了什么
public FragmentTransaction addToBackStack(@Nullable String name) {
if (!mAllowAddToBackStack) {
throw new IllegalStateException(
"This FragmentTransaction is not allowed to be added to the back stack.");
}
//这里呼应了BackStackRecord的generateOps,会把事务加入到fragmentManager的mBackStack列表中
mAddToBackStack = true;
//这是我们自己设置的名字,可以为null
mName = name;
return this;
}
popBackStack做了什么
这里就拿最简单的fragmentManager.popBackStack()来讨论
public void popBackStack() {
//很熟悉的方法enqueueAction,也是向列表中提交事务,不过这里实例化了一个PopBackStackState对象,有必要看一下
enqueueAction(new PopBackStackState(null, -1, 0), false);
}
private class PopBackStackState implements OpGenerator {
final String mName;
final int mId;
final int mFlags;
//PopBackStackState也实现了OpGenerator接口,目前name==null,id==-1,flag==0
PopBackStackState(@Nullable String name, int id, int flags) {
mName = name;
mId = id;
mFlags = flags;
}
}
目前来看popBackStack和add、replace构建的action是不一样的,一个是BackStackRecord一个是PopBackStackState
构建完成后就都是向fragmentManager的队列中放入action并执行,事务的来源已经不一样了,generateOps当然也不一样,这里就呼应了流程图的这部分:
来看一下PopBackStackState中的generateOps
@Override
public boolean generateOps(@NonNull ArrayList<BackStackRecord> records,
@NonNull ArrayList<Boolean> isRecordPop) {
//已省略...
//目前name==null,id==-1,flag==0
return popBackStackState(records, isRecordPop, mName, mId, mFlags);
}
核心是popBackStackState现在来看一下
@SuppressWarnings({"unused", "WeakerAccess"}) /* synthetic access */
boolean popBackStackState(@NonNull ArrayList<BackStackRecord> records,
@NonNull ArrayList<Boolean> isRecordPop, @Nullable String name, int id, int flags) {
if (mBackStack == null) {
return false;
}
//由于目前name==null,id==-1,flag==0所以会直接进入if的判断中
if (name == null && id < 0 && (flags & POP_BACK_STACK_INCLUSIVE) == 0) {
//这里直接把返回栈的最后一个数据放入records列表中并且isRecordPop的数据也为true
int last = mBackStack.size() - 1;
if (last < 0) {
return false;
}
//需要注意这里保存的数据是之前提交的事务
records.add(mBackStack.remove(last));
isRecordPop.add(true);
} else {
int index = -1;
if (name != null || id >= 0) {
// If a name or ID is specified, look for that place in
// the stack.
index = mBackStack.size() - 1;
while (index >= 0) {
BackStackRecord bss = mBackStack.get(index);
if (name != null && name.equals(bss.getName())) {
break;
}
if (id >= 0 && id == bss.mIndex) {
break;
}
index--;
}
if (index < 0) {
return false;
}
if ((flags & POP_BACK_STACK_INCLUSIVE) != 0) {
index--;
// Consume all following entries that match.
while (index >= 0) {
BackStackRecord bss = mBackStack.get(index);
if ((name != null && name.equals(bss.getName()))
|| (id >= 0 && id == bss.mIndex)) {
index--;
continue;
}
break;
}
}
}
if (index == mBackStack.size() - 1) {
return false;
}
for (int i = mBackStack.size() - 1; i > index; i--) {
records.add(mBackStack.remove(i));
isRecordPop.add(true);
}
}
return true;
}
至此对于popBackStack()方法的数据已经构建完成,则继续执行以下流程:
在executeOps方法会判断是否是出栈如果是则执行executePopOps方法:
//BackStackRecord
//可以看出这里是和当前事务执行相反的操作,比如之前的事务的操作是OP_ADD
//这里判断到是case OP_ADD时是执行remove操作
void executePopOps(boolean moveToState) {
for (int opNum = mOps.size() - 1; opNum >= 0; opNum--) {
final Op op = mOps.get(opNum);
Fragment f = op.mFragment;
if (f != null) {
f.setPopDirection(true);
f.setNextTransition(FragmentManager.reverseTransit(mTransition));
// Reverse the target and source names for pop operations
f.setSharedElementNames(mSharedElementTargetNames, mSharedElementSourceNames);
}
switch (op.mCmd) {
case OP_ADD:
f.setAnimations(op.mEnterAnim, op.mExitAnim, op.mPopEnterAnim, op.mPopExitAnim);
mManager.setExitAnimationOrder(f, true);
mManager.removeFragment(f);
break;
case OP_REMOVE:
f.setAnimations(op.mEnterAnim, op.mExitAnim, op.mPopEnterAnim, op.mPopExitAnim);
mManager.addFragment(f);
break;
case OP_HIDE:
f.setAnimations(op.mEnterAnim, op.mExitAnim, op.mPopEnterAnim, op.mPopExitAnim);
mManager.showFragment(f);
break;
当executeOps执行完成后,所有的准备就全部结束了,后续的操作就和add这些是一样的了,通过moveToExpectedState把fragment移动到期望的生命周期状态。
popBackStack系列方法会调用 popBackStackState 构造
records和isRecordPop列表,isRecordPop的内部元素的值均为true 后续流程和提交事务是一样的,根据isRecordPop值的不同选择执行executePopOps或executeOps方法
最后总结一点:对于popBackStack(String name, int flag),name为 addToBackStack(String name) 的参数,如果只调用popBackStack()name为null,flag为0,通过name能找到回退栈的特定元素,flag可以为 0 或者
FragmentManager.POP_BACK_STACK_INCLUSIVE,0 表示只弹出该元素以上的所有元素,POP_BACK_STACK_INCLUSIVE表示弹出包含该元素及以上的所有元素。这里说的弹出所有元素包含回退这些事务,具体可以参考popBackStackState方法中的源码。