本文基于androidx.fragment:fragment:1.5.4分析
先抛出问题:
1. fragment 生命周期到底是如何调度的?
2. add/replace show/hide remove addToBackStack ...... 各种事务的操作符到底对fragment生命周期有着怎样的影响呢?
fragment 调度的主要流程
接下来关注最重要的方法 executeOpsTogether
private void executeOpsTogether(@NonNull ArrayList<BackStackRecord> records,
@NonNull ArrayList<Boolean> isRecordPop, int startIndex, int endIndex) {
// 第一步: 拆解操作
...
if (!isPop) {
oldPrimaryNav = record.expandOps(mTmpAddedFragments, oldPrimaryNav);
} else {
oldPrimaryNav = record.trackAddedFragmentsInPop(mTmpAddedFragments, oldPrimaryNav);
}
...
// 第二步: 执行相关的fragment相关操作 根据cmdOp执行mManager.showFragment(f)等操作
executeOps(records, isRecordPop, startIndex, endIndex);
// 第三步:调度生命周期
// 1. 调度生命周期
// moveToExpectedState 中
// case Fragment.ACTIVITY_CREATED
// case Fragment.AWAITING_EXIT_EFFECTS
// 会添加 SpecialEffectsController 辅助调度生命周期
...
fragmentStateManager.moveToExpectedState();
...
// 2. 辅助调度生命周期, 该方法中最终会调用到 fragmentStateManager.moveToExpectedState();
...
controller.executePendingOperations();
...
}
expandOps
解析操作符是在BackStackRecord中的expandOps方法中
我们主要关注的是
OP_ADD OP_ATTACH
OP_REMOVE OP_DETACH
OP_REPLACE 会将 操作分解为两步,
1. 旧fragment的remove
2. 新fragment的add
这几个操作会影响fragment的生命周期
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: {
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) {
if (old == f) {
alreadyAdded = true;
} else {
if (old == oldPrimaryNav) {
mOps.add(opNum, new Op(OP_UNSET_PRIMARY_NAV, old, true));
opNum++;
oldPrimaryNav = null;
}
final Op removeOp = new Op(OP_REMOVE, old, true);
removeOp.mEnterAnim = op.mEnterAnim;
removeOp.mPopEnterAnim = op.mPopEnterAnim;
removeOp.mExitAnim = op.mExitAnim;
removeOp.mPopExitAnim = op.mPopExitAnim;
mOps.add(opNum, removeOp);
added.remove(old);
opNum++;
}
}
}
if (alreadyAdded) {
mOps.remove(opNum);
opNum--;
} else {
op.mCmd = OP_ADD;
op.mFromExpandedOp = true;
added.add(f);
}
}
break;
case OP_SET_PRIMARY_NAV: {
mOps.add(opNum, new Op(OP_UNSET_PRIMARY_NAV, oldPrimaryNav, true));
op.mFromExpandedOp = true;
opNum++;
oldPrimaryNav = op.mFragment;
}
break;
}
}
return oldPrimaryNav;
}
executeOps
record.bumpBackStackNesting 这个方法的关注点在于:
改变了fragment 中的mBackStackNesting属性的值, 这个是会影响fragment的生命周期执行的
record.executeOps这个方法的关注点在于:
case OP_HIDE
case OP_SHOW
会改变fragment的mHiddenChanged和mHidden属性的值
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);
record.executePopOps();
} else {
record.bumpBackStackNesting(1);
record.executeOps();
}
}
}
// 这里很重要,改变了fragment 中的mBackStackNesting属性的值
void bumpBackStackNesting(int amt) {
if (!mAddToBackStack) {
return;
}
if (FragmentManager.isLoggingEnabled(Log.VERBOSE)) {
Log.v(TAG, "Bump nesting in " + this + " by " + amt);
}
final int numOps = mOps.size();
for (int opNum = 0; opNum < numOps; opNum++) {
final Op op = mOps.get(opNum);
if (op.mFragment != null) {
op.mFragment.mBackStackNesting += amt;
if (FragmentManager.isLoggingEnabled(Log.VERBOSE)) {
Log.v(TAG, "Bump nesting of "
+ op.mFragment + " to " + op.mFragment.mBackStackNesting);
}
}
}
}
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.mBeingSaved = mBeingSaved;
f.setPopDirection(false);
f.setNextTransition(mTransition);
f.setSharedElementNames(mSharedElementSourceNames, mSharedElementTargetNames);
}
switch (op.mCmd) {
case OP_ADD:
f.setAnimations(op.mEnterAnim, op.mExitAnim, op.mPopEnterAnim, op.mPopExitAnim);
mManager.setExitAnimationOrder(f, false);
mManager.addFragment(f);
break;
case OP_REMOVE:
f.setAnimations(op.mEnterAnim, op.mExitAnim, op.mPopEnterAnim, op.mPopExitAnim);
mManager.removeFragment(f);
break;
case OP_HIDE:
f.setAnimations(op.mEnterAnim, op.mExitAnim, op.mPopEnterAnim, op.mPopExitAnim);
mManager.hideFragment(f);
break;
case OP_SHOW:
f.setAnimations(op.mEnterAnim, op.mExitAnim, op.mPopEnterAnim, op.mPopExitAnim);
mManager.setExitAnimationOrder(f, false);
mManager.showFragment(f);
break;
case OP_DETACH:
f.setAnimations(op.mEnterAnim, op.mExitAnim, op.mPopEnterAnim, op.mPopExitAnim);
mManager.detachFragment(f);
break;
case OP_ATTACH:
f.setAnimations(op.mEnterAnim, op.mExitAnim, op.mPopEnterAnim, op.mPopExitAnim);
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);
}
}
}
moveToExpectedState
这个方法的源代码很长,我们可以关注重点:
moveToExpectedState 中while循环退出的条件就是 computeExpectedState 返回值 和 mFragment.mState相等
moveToExpectedState中重点在于:
case Fragment.ACTIVITY_CREATED
case Fragment.AWAITING_EXIT_EFFECTS
这两个case往SpecialEffectsController中加入了相关操作
maxState 是关键,控制 moveToExpectedState 退出循环的
mFragment.isInBackStack() 重点,这个方法决定了fragment的生命周期是否执行onDestroyView后面的生命周期方法
int computeExpectedState() {
// If the FragmentManager is null, disallow changing the state at all
if (mFragment.mFragmentManager == null) {
return mFragment.mState;
}
// Assume the Fragment can go as high as the FragmentManager's state
int maxState = mFragmentManagerState;
// Don't allow the Fragment to go above its max lifecycle state
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);
}
// For fragments that are created from a layout using the <fragment> tag (mFromLayout)
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);
}
}
}
// Fragments that are not currently added will sit in the CREATED state.
if (!mFragment.mAdded) {
maxState = Math.min(maxState, Fragment.CREATED);
}
//
SpecialEffectsController.Operation.LifecycleImpact awaitingEffect = null;
if (mFragment.mContainer != null) {
SpecialEffectsController controller = SpecialEffectsController.getOrCreateController(
mFragment.mContainer, mFragment.getParentFragmentManager());
awaitingEffect = controller.getAwaitingCompletionLifecycleImpact(this);
}
if (awaitingEffect == SpecialEffectsController.Operation.LifecycleImpact.ADDING) {
// Fragments awaiting their enter effects cannot proceed beyond that state
// 这里控制fragment走resume生命周期方法
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);
} else if (mFragment.mRemoving) {
// 这里会控制 fragment 是否走 detach 生命周期方法
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);
}
}
// Defer start if requested; don't allow it to move to STARTED or higher
// if it's not already started.
if (mFragment.mDeferStart && mFragment.mState < Fragment.STARTED) {
maxState = Math.min(maxState, Fragment.ACTIVITY_CREATED);
}
if (FragmentManager.isLoggingEnabled(Log.VERBOSE)) {
Log.v(FragmentManager.TAG, "computeExpectedState() of " + maxState + " for "
+ mFragment);
}
return maxState;
}
void moveToExpectedState() {
if (mMovingToState) {
if (FragmentManager.isLoggingEnabled(Log.VERBOSE)) {
Log.v(FragmentManager.TAG, "Ignoring re-entrant call to "
+ "moveToExpectedState() for " + getFragment());
}
return;
}
try {
mMovingToState = true;
boolean stateWasChanged = false;
int newState;
while ((newState = computeExpectedState()) != mFragment.mState) {
stateWasChanged = true;
if (newState > mFragment.mState) {
// Moving upward
int nextStep = mFragment.mState + 1;
switch (nextStep) {
case Fragment.ATTACHED:
attach();
break;
case Fragment.CREATED:
create();
break;
case Fragment.VIEW_CREATED:
ensureInflatedView();
createView();
break;
case Fragment.AWAITING_EXIT_EFFECTS:
activityCreated();
break;
case Fragment.ACTIVITY_CREATED:
if (mFragment.mView != null && mFragment.mContainer != null) {
SpecialEffectsController controller = SpecialEffectsController
.getOrCreateController(mFragment.mContainer,
mFragment.getParentFragmentManager());
int visibility = mFragment.mView.getVisibility();
SpecialEffectsController.Operation.State finalState =
SpecialEffectsController.Operation.State.from(visibility);
// 加入该操作,是为后面执行 fragment 的resume 生命周期方法
controller.enqueueAdd(finalState, this);
}
mFragment.mState = Fragment.ACTIVITY_CREATED;
break;
case Fragment.STARTED:
start();
break;
case Fragment.AWAITING_ENTER_EFFECTS:
mFragment.mState = Fragment.AWAITING_ENTER_EFFECTS;
break;
case Fragment.RESUMED:
resume();
break;
}
} else {
// Moving downward
int nextStep = mFragment.mState - 1;
switch (nextStep) {
case Fragment.AWAITING_ENTER_EFFECTS:
pause();
break;
case Fragment.STARTED:
mFragment.mState = Fragment.STARTED;
break;
case Fragment.ACTIVITY_CREATED:
stop();
break;
case Fragment.AWAITING_EXIT_EFFECTS:
if (FragmentManager.isLoggingEnabled(Log.DEBUG)) {
Log.d(TAG, "movefrom ACTIVITY_CREATED: " + mFragment);
}
if (mFragment.mBeingSaved) {
saveState();
} else if (mFragment.mView != null) {
// Need to save the current view state if not done already
// by saveInstanceState()
if (mFragment.mSavedViewState == null) {
saveViewState();
}
}
if (mFragment.mView != null && mFragment.mContainer != null) {
SpecialEffectsController controller = SpecialEffectsController
.getOrCreateController(mFragment.mContainer,
mFragment.getParentFragmentManager());
// 加入该操作,是为后面执行 旧fragment 执行 destroyView ----- detach 等生命周期方法
// 执行完 destroyView 后,是否执行后面的生命周期方法取决于当前回退栈中是否有fragment,
// 没有则往后面执行,否则停止
controller.enqueueRemove(this);
}
mFragment.mState = Fragment.AWAITING_EXIT_EFFECTS;
break;
case Fragment.VIEW_CREATED:
mFragment.mInLayout = false;
mFragment.mState = Fragment.VIEW_CREATED;
break;
case Fragment.CREATED:
destroyFragmentView();
mFragment.mState = Fragment.CREATED;
break;
case Fragment.ATTACHED:
if (mFragment.mBeingSaved
&& mFragmentStore.getSavedState(mFragment.mWho) == null) {
saveState();
}
destroy();
break;
case Fragment.INITIALIZING:
detach();
break;
}
}
}
if (!stateWasChanged && mFragment.mState == Fragment.INITIALIZING) {
// If the state wasn't changed and the Fragment should be removed
// then we need to do the work of destroy()+detach() here
// to ensure the FragmentManager is in a cleaned up state
if (mFragment.mRemoving && !mFragment.isInBackStack() && !mFragment.mBeingSaved) {
if (FragmentManager.isLoggingEnabled(Log.DEBUG)) {
Log.d(TAG, "Cleaning up state of never attached fragment: " + mFragment);
}
mFragmentStore.getNonConfig().clearNonConfigState(mFragment);
mFragmentStore.makeInactive(this);
if (FragmentManager.isLoggingEnabled(Log.DEBUG)) {
Log.d(TAG, "initState called for fragment: " + mFragment);
}
mFragment.initState();
}
}
// show / hide 调度 fragment 的 onHiddenChanged 方法,这两个命令不会影响fragment的生命周期
if (mFragment.mHiddenChanged) {
if (mFragment.mView != null && mFragment.mContainer != null) {
// Get the controller and enqueue the show/hide
SpecialEffectsController controller = SpecialEffectsController
.getOrCreateController(mFragment.mContainer,
mFragment.getParentFragmentManager());
if (mFragment.mHidden) {
controller.enqueueHide(this);
} else {
controller.enqueueShow(this);
}
}
if (mFragment.mFragmentManager != null) {
mFragment.mFragmentManager.invalidateMenuForFragment(mFragment);
}
mFragment.mHiddenChanged = false;
mFragment.onHiddenChanged(mFragment.mHidden);
mFragment.mChildFragmentManager.dispatchOnHiddenChanged();
}
} finally {
mMovingToState = false;
}
}
总结
add/replace/remove 会影响生命周期
show/hide 不会影响生命周期,只会调用 onHiddenChanged方法
addToBackStack 这个是会影响生命周期的