平时开发中经常使用Fragment的场景是创建Fragment并添加到FragmentActivity的指定布局容器中。要实现这样的操作,首先需要获取FragmentManager,接着开启事务FragmentTransaction,并添加add、remove、replace、hide、show等等操作,最后commitXXX提交事务执行对应操作。
接下来进入源码追踪这个过程,看看FragmentManager是如何进行调度执行。
文中源码基于’androidx.fragment:fragment:1.1.0’
在FragmentActivity中通过getSupportFragmentManager方法来获取FragmentManager:
[FragmentActivity.java]
public FragmentManager getSupportFragmentManager() {
return mFragments.getSupportFragmentManager();
}
该方法中又通过mFragments成员来获取:
[FragmentController.java]
public FragmentManager getSupportFragmentManager() {
return mHost.mFragmentManager;
}
其中又通过mHost成员来获取。
在研究FragmentManager之前,先来看看mFragments、mHost是什么。
先来看看FragmentActivity的mFragments成员:
[FragmentActivity.java]
public class FragmentActivity extends ComponentActivity implements
ActivityCompat.OnRequestPermissionsResultCallback,
ActivityCompat.RequestPermissionsRequestCodeValidator {
// ···
final FragmentController mFragments = FragmentController.createController(new HostCallbacks());
// ···
}
mFragments为FragmentController对象。
接着看createController方法,这里传入HostCallbacks实例:
[FragmentController.java]
public static FragmentController createController(@NonNull FragmentHostCallback<?> callbacks) {
return new FragmentController(checkNotNull(callbacks, "callbacks == null"));
}
private FragmentController(FragmentHostCallback<?> callbacks) {
// 持有HostCallbacks引用
mHost = callbacks;
}
在创建FragmentController时,实例化了HostCallbacks并赋值给FragmentController的mHost成员。
[FragmentActivity.java]
class HostCallbacks extends FragmentHostCallback<FragmentActivity> implements
ViewModelStoreOwner,
OnBackPressedDispatcherOwner {
public HostCallbacks() {
super(FragmentActivity.this /*fragmentActivity*/);
}
// ···
}
HostCallbacks继承自FragmentHostCallback,为FragmentActivity的内部类,持有FragmentActivity的引用。
[FragmentHostCallback.java]
public abstract class FragmentHostCallback<E> extends FragmentContainer {
// ···
FragmentHostCallback(@NonNull FragmentActivity activity) {
this(activity, activity /*context*/, new Handler(), 0 /*windowAnimations*/);
}
FragmentHostCallback(@Nullable Activity activity, @NonNull Context context,
@NonNull Handler handler, int windowAnimations) {
// 持有FragmentActivity上下文引用
mActivity = activity;
mContext = Preconditions.checkNotNull(context, "context == null");
// 构造函数中创建的Handler,默认运行在主线程
mHandler = Preconditions.checkNotNull(handler, "handler == null");
// 动画相关,默认为0
mWindowAnimations = windowAnimations;
}
// ···
}
可以看出HostCallbacks持有当前FragmentActivity上下文,并创建了一个主线程Handler。
FragmentManager为抽象类,而FragmentManagerImpl是其实现类:
[FragmentManagerImpl.java]
final class FragmentManagerImpl extends FragmentManager implements LayoutInflater.Factory2 {
// ···
}
在FragmentHostCallback实例化时会创建FragmentManagerImpl:
[FragmentHostCallback.java]
public abstract class FragmentHostCallback<E> extends FragmentContainer {
// ···
final FragmentManagerImpl mFragmentManager = new FragmentManagerImpl();
// ···
}
FragmentHostCallback的mFragmentManager成员持有FragmentManagerImpl。
在FragmentActivity的onCreate方法中:
[FragmentActivity.java]
protected void onCreate(@Nullable Bundle savedInstanceState) {
// 调用FragmentController的attachHost方法,参数传null
mFragments.attachHost(null /*parent*/);
// ···
}
接着看attachHost方法:
[FragmentController.java]
public void attachHost(@Nullable Fragment parent) {
// 调用FragmentManagerImpl的attachController方法,并传入HostCallbacks实例,参数parent为null。
mHost.mFragmentManager.attachController(
mHost, mHost /*container*/, parent);
}
进入FragmentManagerImpl的attachController方法:
[FragmentManagerImpl.java]
public void attachController(@NonNull FragmentHostCallback host,
@NonNull FragmentContainer container, @Nullable final Fragment parent) {
if (mHost != null) throw new IllegalStateException("Already attached");
// 持有HostCallbacks引用
mHost = host;
mContainer = container;
mParent = parent;
if (mParent != null) {
// Since the callback depends on us being the primary navigation fragment,
// update our callback now that we have a parent so that we have the correct
// state by default
updateOnBackPressedCallbackEnabled();
}
// Set up the OnBackPressedCallback
// 省略BackPressed设置部分
// ···
// Get the FragmentManagerViewModel
// 省略ViewModel设置部分
// ···
}
FragmentActivity在onCreate中进行FragmentManagerImpl的绑定操作,在FragmentManagerImpl的attachController方法中接收HostCallbacks实例并保存。
FragmentActivity持有FragmentController引用,FragmentController持有HostCallbacks引用,HostCallbacks持有FragmentActivity引用,FragmentActivity和FragmentManagerImpl互相持有引用。
FragmentActivity通过FragmentController获取HostCallbacks,再通过HostCallbacks间接调用FragmentManagerImpl。FragmentManagerImpl通过HostCallbacks来间接获取上下文和执行回调方法。
获取到FragmentManagerImpl实例后,通过它的beginTransaction方法开启一个事务:
[FragmentManagerImpl.java]
public FragmentTransaction beginTransaction() {
return new BackStackRecord(this);
}
这里创建BackStackRecord(继承自FragmentTransaction,并实现BackStackEntry、OpGenerator接口),BackStackRecord将持有FragmentManagerImpl。
FragmentTransaction封装一个事务,一个事务包含一组操作(单个或多个操作)。
这里以,往FragmentActivity中添加一个Fragment为例。
通常添加Fragment是通过调用FragmentTransaction的add方法,传入布局ID和Fragment实例:
[FragmentTransaction.java]
public FragmentTransaction add(@IdRes int containerViewId, @NonNull Fragment fragment,
@Nullable String tag) {
// tag可选参数,可通过tag查找fragment,OP_ADD标识add操作类型
doAddOp(containerViewId, fragment, tag, OP_ADD);
return this;
}
BackStackRecord重写了doAddOp方法:
[BackStackRecord.java]
void doAddOp(int containerViewId, Fragment fragment, @Nullable String tag, int opcmd) {
super.doAddOp(containerViewId, fragment, tag, opcmd);
// 将持有的FragmentManagerImpl赋值给Fragment的mFragmentManager成员
fragment.mFragmentManager = mManager;
}
该方法中通过super还是调用FragmentTransaction的doAddOp,只是在执行完后为Fragment的mFragmentManager成员赋值。
[FragmentTransaction.java]
void doAddOp(int containerViewId, Fragment fragment, @Nullable String tag, int opcmd) {
final Class<?> fragmentClass = fragment.getClass();
final int modifiers = fragmentClass.getModifiers();
// 检查fragment是否是匿名类,或者非public访问性,或者定义在另一个类中但没有声明static
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) {
// 检查是否fragment已有tag但和当前传入的tag不同
if (fragment.mTag != null && !tag.equals(fragment.mTag)) {
throw new IllegalStateException("Can't change tag of fragment "
+ fragment + ": was " + fragment.mTag
+ " now " + tag);
}
// fragment保存tag
fragment.mTag = tag;
}
// containerViewId即为FragmentActivity中用于添加这个fragment的布局容器ID
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");
}
// 检查是否fragment已经设置容器ID但与当前传入的ID不同
if (fragment.mFragmentId != 0 && fragment.mFragmentId != containerViewId) {
throw new IllegalStateException("Can't change container ID of fragment "
+ fragment + ": was " + fragment.mFragmentId
+ " now " + containerViewId);
}
// fragment保存容器ID,mFragmentId默认为容器ID
fragment.mContainerId = fragment.mFragmentId = containerViewId;
}
// 添加操作
addOp(new Op(opcmd, fragment));
}
该方法中做了以下几步:
Op表示一个操作,看它的构造函数:
[FragmentTransaction.java]
Op(int cmd, Fragment fragment) {
// 保存操作类型
this.mCmd = cmd;
// 保存待操作的fragment
this.mFragment = fragment;
// 生命周期状态置为RESUMED,对应Activity执行onResume之后的状态
this.mOldMaxState = Lifecycle.State.RESUMED;
this.mCurrentMaxState = Lifecycle.State.RESUMED;
}
[FragmentTransaction.java]
void addOp(Op op) {
// 保存Op对象
mOps.add(op);
// 动画相关,默认都为0
op.mEnterAnim = mEnterAnim;
op.mExitAnim = mExitAnim;
op.mPopEnterAnim = mPopEnterAnim;
op.mPopExitAnim = mPopExitAnim;
}
FragmentTransaction的mOps成员用于保存Op对象,mOps为ArrayList。
FragmentTransaction有四个提交事务的方法:commit、commitAllowingStateLoss、commitNow、commitNowAllowingStateLoss。这四个方法都为抽象类,具体实现在BackStackRecord中。
这里以commitAllowingStateLoss为例:
[BackStackRecord.java]
public int commitAllowingStateLoss() {
return commitInternal(true);
}
int commitInternal(boolean allowStateLoss) {
if (mCommitted) throw new IllegalStateException("commit already called");
// 省略DEBUG部分 ···
mCommitted = true;
// mAddToBackStack默认为false,若调用addToBackStack方法的话为true
if (mAddToBackStack) {
mIndex = mManager.allocBackStackIndex(this);
} else {
mIndex = -1;
}
// 此时传入的allowStateLoss为true
// 通过FragmentManagerImpl入队
mManager.enqueueAction(this, allowStateLoss);
return mIndex;
}
接着看FragmentManagerImpl的enqueueAction方法,此时传入BackStackRecord自身和true:
[FragmentManagerImpl.java]
public void enqueueAction(OpGenerator action, boolean allowStateLoss) {
if (!allowStateLoss) {
checkStateLoss();
}
synchronized (this) {
if (mDestroyed || mHost == null) {
if (allowStateLoss) {
// This FragmentManager isn't attached, so drop the entire transaction.
return;
}
throw new IllegalStateException("Activity has been destroyed");
}
if (mPendingActions == null) {
mPendingActions = new ArrayList<>();
}
// mPendingActions表示待执行操作集合,action即为BackStackRecord(实现了OpGenerator接口)
mPendingActions.add(action);
scheduleCommit();
}
}
接着看scheduleCommit方法:
[FragmentManagerImpl.java]
void scheduleCommit() {
synchronized (this) {
// 标记是否存在延迟事务,默认不存在
boolean postponeReady =
mPostponedTransactions != null && !mPostponedTransactions.isEmpty();
// 标记是否仅存在一个待执行事务,第一次通过enqueueAction提交事务时符合条件
boolean pendingReady = mPendingActions != null && mPendingActions.size() == 1;
if (postponeReady || pendingReady) {
// 符合条件,通过Handler调度任务执行
mHost.getHandler().removeCallbacks(mExecCommit);
mHost.getHandler().post(mExecCommit);
updateOnBackPressedCallbackEnabled();
}
}
}
当存在延迟事务或第一次提交事务时,会通过Handler来post一个Runnable执行操作,这里的Handler即HostCallbacks实例化时创建的主线程Handler。
可见通过commit、commitAllowingStateLoss方法提交的事务不会立即执行,而是等待主线程LOOPER下一次取出消息时执行。
前文中使用Handler post的mExecCommit是一个Runnable:
[FragmentManagerImpl.java]
Runnable mExecCommit = new Runnable() {
@Override
public void run() {
execPendingActions();
}
};
触发时将调用execPendingActions方法处理事务操作:
[FragmentManagerImpl.java]
public boolean execPendingActions() {
// 检查状态和初始化mTmpRecords、mTmpIsPop集合和处理延迟事务
ensureExecReady(true);
boolean didSomething = false;
// 生成命令并保存在mTmpRecords、mTmpIsPop集合中
while (generateOpsForPendingActions(mTmpRecords, mTmpIsPop)) {
// 标记当前处于执行事务中
mExecutingActions = true;
try {
// 移除或合并多余的操作并执行
removeRedundantOperationsAndExecute(mTmpRecords, mTmpIsPop);
} finally {
cleanupExec();
}
didSomething = true;
}
updateOnBackPressedCallbackEnabled();
// 执行推迟启动的Fragment
doPendingDeferredStart();
// 清理mActive集合
burpActive();
return didSomething;
}
该方法中会在一个while循环中检索待执行事务并执行,当generateOpsForPendingActions返回false表示没有待执行的事务,则结束while循环。
两个集合的说明:
[FragmentManagerImpl.java]
private boolean generateOpsForPendingActions(ArrayList<BackStackRecord> records,
ArrayList<Boolean> isPop) {
// 标记是否有执行事务
boolean didSomething = false;
synchronized (this) {
// 若不存在待执行事务则返回false
if (mPendingActions == null || mPendingActions.size() == 0) {
return false;
}
final int numActions = mPendingActions.size();
// 遍历mPendingActions,此时仅有一个OP_ADD类型的BackStackRecord
for (int i = 0; i < numActions; i++) {
// 依次调用generateOps方法
didSomething |= mPendingActions.get(i).generateOps(records, isPop);
}
// 清空mPendingActions
mPendingActions.clear();
// 移除mExecCommit,避免冗余执行
mHost.getHandler().removeCallbacks(mExecCommit);
}
return didSomething;
}
这里以添加Fragment为例,此时mPendingActions中存在一个OP_ADD类型的BackStackRecord,查看它的generateOps方法:
[BackStackRecord.java]
public boolean generateOps(ArrayList<BackStackRecord> records, ArrayList<Boolean> isRecordPop) {
if (FragmentManagerImpl.DEBUG) {
Log.v(TAG, "Run: " + this);
}
// records集合添加BackStackRecord自身
records.add(this);
// isRecordPop添加false
isRecordPop.add(false);
// mAddToBackStack默认为false,因此不加入回退栈
if (mAddToBackStack) {
mManager.addBackStackState(this);
}
return true;
}
[FragmentManagerImpl.java]
private void removeRedundantOperationsAndExecute(ArrayList<BackStackRecord> records,
ArrayList<Boolean> isRecordPop) {
if (records == null || records.isEmpty()) {
return;
}
if (isRecordPop == null || records.size() != isRecordPop.size()) {
throw new IllegalStateException("Internal error with the back stack records");
}
// Force start of any postponed transactions that interact with scheduled transactions:
executePostponedTransaction(records, isRecordPop);
final int numRecords = records.size();
int startIndex = 0;
for (int recordNum = 0; recordNum < numRecords; recordNum++) {
// 标记是否支持操作排序优化,默认为false
final boolean canReorder = records.get(recordNum).mReorderingAllowed;
if (!canReorder) {
// execute all previous transactions
if (startIndex != recordNum) {
executeOpsTogether(records, isRecordPop, startIndex, recordNum);
}
// execute all pop operations that don't allow reordering together or
// one add operation
int reorderingEnd = recordNum + 1;
// 非pop事务都返回false
if (isRecordPop.get(recordNum)) {
while (reorderingEnd < numRecords
&& isRecordPop.get(reorderingEnd)
&& !records.get(reorderingEnd).mReorderingAllowed) {
reorderingEnd++;
}
}
// 执行指定索引区间中的BackStackRecord
executeOpsTogether(records, isRecordPop, recordNum, reorderingEnd);
startIndex = reorderingEnd;
recordNum = reorderingEnd - 1;
}
}
if (startIndex != numRecords) {
// 开启操作排序优化情况下可能会满足该if条件
executeOpsTogether(records, isRecordPop, startIndex, numRecords);
}
}
当有多个待执行事务时,FragmentManager会删除部分冗余事务操作。例如:
排序优化操作会导致出现超出开发者预期的行为,因此默认不进行此操作。
进入executeOpsTogether方法:
[FragmentManagerImpl.java]
private void executeOpsTogether(ArrayList<BackStackRecord> records,
ArrayList<Boolean> isRecordPop, int startIndex, int endIndex) {
// ···
executeOps(records, isRecordPop, startIndex, endIndex);
// ···
}
进入executeOps方法:
[FragmentManagerImpl.java]
private static void executeOps(ArrayList<BackStackRecord> records,
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);
// OP_ADD类型执行executeOps
record.executeOps();
}
}
}
看BackStackRecord的executeOps方法中的OP_ADD case:
[BackStackRecord.java]
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);
// 添加Fragment
mManager.addFragment(f, false);
break;
// 省略其他case ···
default:
throw new IllegalArgumentException("Unknown cmd: " + op.mCmd);
}
if (!mReorderingAllowed && op.mCmd != OP_ADD && f != null) {
mManager.moveFragmentToExpectedState(f);
}
}
// mReorderingAllowed默认为false
if (!mReorderingAllowed) {
// Added fragments are added at the end to comply with prior behavior.
// 更新状态,这里传入FragmentManagerImpl的当前状态和true
mManager.moveToState(mManager.mCurState, true);
}
}
该方法中处理OP_ADD时,首先通过addFragment方法添加fragment至集合中保存,最后通过moveToState更新状态并设置fragment。
[FragmentManagerImpl.java]
public void addFragment(Fragment fragment, boolean moveToStateNow) {
if (DEBUG) Log.v(TAG, "add: " + fragment);
// 将fragment添加至mActive集合保存,若设置setRetainInstance还将添加入FragmentManagerViewModel中保存
makeActive(fragment);
// 此时为OP_ADD操作,mDetached为false
if (!fragment.mDetached) {
if (mAdded.contains(fragment)) {
throw new IllegalStateException("Fragment already added: " + fragment);
}
synchronized (mAdded) {
// fragment加入mAdded集合
mAdded.add(fragment);
}
// mAdded用于标记该fragment是否已经加入mAdded集合
fragment.mAdded = true;
// mRemoving标记该fragment是否从Activity移除
fragment.mRemoving = false;
// 此时mView还未生成,为null
if (fragment.mView == null) {
fragment.mHiddenChanged = false;
}
if (isMenuAvailable(fragment)) {
mNeedMenuInvalidate = true;
}
// 此时传入的moveToStateNow为false
if (moveToStateNow) {
moveToState(fragment);
}
}
}
将fragment添加入mActive和mAdded集合中。
回到BackStackRecord.executeOps方法中,在方法的最后执行moveToState方法:
[FragmentManagerImpl.java]
void moveToState(int newState, boolean always) {
if (mHost == null && newState != Fragment.INITIALIZING) {
throw new IllegalStateException("No activity");
}
if (!always && newState == mCurState) {
return;
}
// 更新状态,此时传入的newState和mCurState相等
mCurState = newState;
// Must add them in the proper order. mActive fragments may be out of order
final int numAdded = mAdded.size();
// 遍历mAdded,依次取出Fragment处理
for (int i = 0; i < numAdded; i++) {
Fragment f = mAdded.get(i);
moveFragmentToExpectedState(f);
}
// 省略···
}
该方法中依次取出Fragment,调用moveFragmentToExpectedState将Fragment根据最终期望的状态进行初始化设置。
mCurState成员记录FragmentManagerImpl的当前状态,状态值有:
看moveFragmentToExpectedState方法:
[FragmentManagerImpl.java]
void moveFragmentToExpectedState(Fragment f) {
if (f == null) {
return;
}
if (!mActive.containsKey(f.mWho)) {
if (DEBUG) {
Log.v(TAG, "Ignoring moving " + f + " to state " + mCurState
+ "since it is not added to " + this);
}
return;
}
int nextState = mCurState;
if (f.mRemoving) {
if (f.isInBackStack()) {
nextState = Math.min(nextState, Fragment.CREATED);
} else {
nextState = Math.min(nextState, Fragment.INITIALIZING);
}
}
// 调度fragment到目标状态对应阶段,并执行对应阶段的初始化设置
moveToState(f, nextState, f.getNextTransition(), f.getNextTransitionStyle(), false);
if (f.mView != null) {
// ···
}
if (f.mHiddenChanged) {
completeShowHideFragment(f);
}
}
该方法中调用另一个moveToState重载方法:
[FragmentManagerImpl.java]
void moveToState(Fragment f, int newState, int transit, int transitionStyle,
boolean keepActive) {
// 省略状态检查校验部分
// ···
// 判断fragment的生命周期状态是否小等于FragmentManager的状态,刚创建添加的fragment状态默认为INITIALIZING
if (f.mState <= newState) {
// ···
switch (f.mState) {
case Fragment.INITIALIZING:
// 开始进入attach阶段
if (newState > Fragment.INITIALIZING) {
if (DEBUG) Log.v(TAG, "moveto CREATED: " + f);
// 省略mSavedFragmentState部分 ···
f.mHost = mHost;
f.mParentFragment = mParent;
f.mFragmentManager = mParent != null
? mParent.mChildFragmentManager : mHost.mFragmentManager;
// If we have a target fragment, push it along to at least CREATED
// so that this one can rely on it as an initialized dependency.
// 省略mTarget部分 ···
// 省略mTargetWho部分 ···
dispatchOnFragmentPreAttached(f, mHost.getContext(), false);
f.performAttach();
if (f.mParentFragment == null) {
mHost.onAttachFragment(f);
} else {
f.mParentFragment.onAttachFragment(f);
}
dispatchOnFragmentAttached(f, mHost.getContext(), false);
if (!f.mIsCreated) {
dispatchOnFragmentPreCreated(f, f.mSavedFragmentState, false);
f.performCreate(f.mSavedFragmentState);
dispatchOnFragmentCreated(f, f.mSavedFragmentState, false);
} else {
f.restoreChildFragmentState(f.mSavedFragmentState);
f.mState = Fragment.CREATED;
}
}
// fall through
// 注意此处无break,会继续往下匹配case执行
case Fragment.CREATED:
// 开始进入CreateView阶段
// We want to unconditionally run this anytime we do a moveToState that
// moves the Fragment above INITIALIZING, including cases such as when
// we move from CREATED => CREATED as part of the case fall through above.
if (newState > Fragment.INITIALIZING) {
ensureInflatedFragmentView(f);
}
if (newState > Fragment.CREATED) {
if (DEBUG) Log.v(TAG, "moveto ACTIVITY_CREATED: " + f);
if (!f.mFromLayout) {
ViewGroup container = null;
if (f.mContainerId != 0) {
if (f.mContainerId == View.NO_ID) {
throwException(new IllegalArgumentException(
"Cannot create fragment "
+ f
+ " for a container view with no id"));
}
// 获取布局容器,通过FragmentActivity.this.findViewById(f.mContainerId)获取
container = (ViewGroup) mContainer.onFindViewById(f.mContainerId);
if (container == null && !f.mRestored) {
String resName;
try {
resName = f.getResources().getResourceName(f.mContainerId);
} catch (Resources.NotFoundException e) {
resName = "unknown";
}
throwException(new IllegalArgumentException(
"No view found for id 0x"
+ Integer.toHexString(f.mContainerId) + " ("
+ resName
+ ") for fragment " + f));
}
}
f.mContainer = container;
// performGetLayoutInflater中通过FragmentActivity上下文获取LayoutInflater
// performCreateView中会触发fragment的onCreateView方法,
// 返回我们自定义的视图,并赋值给mView成员
f.performCreateView(f.performGetLayoutInflater(
f.mSavedFragmentState), container, f.mSavedFragmentState);
if (f.mView != null) {
f.mInnerView = f.mView;
f.mView.setSaveFromParentEnabled(false);
if (container != null) {
// 将fragment的view加入布局容器中
container.addView(f.mView);
}
if (f.mHidden) {
f.mView.setVisibility(View.GONE);
}
f.onViewCreated(f.mView, f.mSavedFragmentState);
dispatchOnFragmentViewCreated(f, f.mView, f.mSavedFragmentState,
false);
// Only animate the view if it is visible. This is done after
// dispatchOnFragmentViewCreated in case visibility is changed
f.mIsNewlyAdded = (f.mView.getVisibility() == View.VISIBLE)
&& f.mContainer != null;
} else {
f.mInnerView = null;
}
}
f.performActivityCreated(f.mSavedFragmentState);
dispatchOnFragmentActivityCreated(f, f.mSavedFragmentState, false);
if (f.mView != null) {
f.restoreViewState(f.mSavedFragmentState);
}
f.mSavedFragmentState = null;
}
// fall through
case Fragment.ACTIVITY_CREATED:
if (newState > Fragment.ACTIVITY_CREATED) {
if (DEBUG) Log.v(TAG, "moveto STARTED: " + f);
f.performStart();
dispatchOnFragmentStarted(f, false);
}
// fall through
case Fragment.STARTED:
if (newState > Fragment.STARTED) {
if (DEBUG) Log.v(TAG, "moveto RESUMED: " + f);
f.performResume();
dispatchOnFragmentResumed(f, false);
f.mSavedFragmentState = null;
f.mSavedViewState = null;
}
}
} else if (f.mState > newState) {
// 省略生命周期逆生长部分,即onPause、onStop、onDestroyView、onDestroy、onDetach
// ···
}
if (f.mState != newState) {
Log.w(TAG, "moveToState: Fragment state for " + f + " not updated inline; "
+ "expected state " + newState + " found " + f.mState);
// 更新fragment的状态
f.mState = newState;
}
}
moveToState方法中在CREATED状态阶段,完成了Fragment视图的创建(若有自定义视图),接着添加至给定的布局容器中。
moveToState方法还会根据Fragment和FragmentManager当前的生命周期状态,调度Fragment的状态更新,在其中还会触发Fragment各阶段的生命周期回调方法。
通过调用BackStackRecord的remove方法,传入指定Fragment,达到移除Fragment的作用。
[BackStackRecord.java]
public FragmentTransaction remove(@NonNull Fragment fragment) {
if (fragment.mFragmentManager != null && fragment.mFragmentManager != mManager) {
throw new IllegalStateException("Cannot remove Fragment attached to "
+ "a different FragmentManager. Fragment " + fragment.toString() + " is already"
+ " attached to a FragmentManager.");
}
return super.remove(fragment);
}
调用父类FragmentTransaction的remove方法:
[FragmentTransaction.java]
public FragmentTransaction remove(@NonNull Fragment fragment) {
addOp(new Op(OP_REMOVE, fragment));
return this;
}
remove方法中创建Op对象,传入命令类型OP_REMOVE和要移除的fragment,添加到命令集合mOps成员中。
接下来的步骤就是提交事务,加入事务队列,等待调度执行,同OP_ADD一样,将会执行BackStackRecord的executeOps方法:
[BackStackRecord.java]
void executeOps() {
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_REMOVE:
f.setNextAnim(op.mExitAnim);
// 将该fragment从FragmentManagerImpl的mAdded成员中移除,并设置
// 该fragment的mAdded成员为false、mRemoving成员为true
mManager.removeFragment(f);
break;
// ···
}
// mReorderingAllowed默认为false
if (!mReorderingAllowed && op.mCmd != OP_ADD && f != null) {
// 更新fragment的生命状态和执行对应阶段的生命周期回调和释放销毁
mManager.moveFragmentToExpectedState(f);
}
}
if (!mReorderingAllowed) {
// Added fragments are added at the end to comply with prior behavior.
// 更新当前FragmentManagerImpl中管理的Fragment的状态
mManager.moveToState(mManager.mCurState, true);
}
}
moveFragmentToExpectedState和moveToState方法在处理OP_ADD命令时见到过,是通用方法,其他命令也都会调用这两个方法。
[FragmentManagerImpl.java]
void moveFragmentToExpectedState(Fragment f) {
// ···
int nextState = mCurState;
// mRemoving此时已经置为true
if (f.mRemoving) {
// 修改要更新至的目标状态,若该fragment不为最后一个,则目标状态为CREATED
if (f.isInBackStack()) {
nextState = Math.min(nextState, Fragment.CREATED);
} else {
nextState = Math.min(nextState, Fragment.INITIALIZING);
}
}
// 调度fragment到目标状态对应阶段,并执行对应阶段的处理
moveToState(f, nextState, f.getNextTransition(), f.getNextTransitionStyle(), false);
// ···
}
[FragmentManagerImpl.java]
void moveToState(Fragment f, int newState, int transit, int transitionStyle,
boolean keepActive) {
// ···
if (f.mState <= newState) {
// ···
} else if (f.mState > newState) {
switch (f.mState) {
case Fragment.RESUMED:
// ···
case Fragment.STARTED:
// ···
case Fragment.ACTIVITY_CREATED:
if (newState < Fragment.ACTIVITY_CREATED) {
if (DEBUG) Log.v(TAG, "movefrom ACTIVITY_CREATED: " + f);
if (f.mView != null) {
// Need to save the current view state if not
// done already.
if (mHost.onShouldSaveFragmentState(f) && f.mSavedViewState == null) {
saveFragmentViewState(f);
}
}
f.performDestroyView();
dispatchOnFragmentViewDestroyed(f, false);
if (f.mView != null && f.mContainer != null) {
// Stop any current animations:
f.mContainer.endViewTransition(f.mView);
f.mView.clearAnimation();
AnimationOrAnimator anim = null;
// If parent is being removed, no need to handle child animations.
if (f.getParentFragment() == null || !f.getParentFragment().mRemoving) {
if (mCurState > Fragment.INITIALIZING && !mDestroyed
&& f.mView.getVisibility() == View.VISIBLE
&& f.mPostponedAlpha >= 0) {
anim = loadAnimation(f, transit, false,
transitionStyle);
}
f.mPostponedAlpha = 0;
if (anim != null) {
animateRemoveFragment(f, anim, newState);
}
// 设置了view和布局容器的情况下,需要从布局中移除该Fragment的view
f.mContainer.removeView(f.mView);
}
}
// 解除引用
f.mContainer = null;
f.mView = null;
// Set here to ensure that Observers are called after
// the Fragment's view is set to null
f.mViewLifecycleOwner = null;
f.mViewLifecycleOwnerLiveData.setValue(null);
f.mInnerView = null;
f.mInLayout = false;
}
// fall through
case Fragment.CREATED:
if (newState < Fragment.CREATED) {
if (mDestroyed) {
// The fragment's containing activity is
// being destroyed, but this fragment is
// currently animating away. Stop the
// animation right now -- it is not needed,
// and we can't wait any more on destroying
// the fragment.
if (f.getAnimatingAway() != null) {
View v = f.getAnimatingAway();
f.setAnimatingAway(null);
v.clearAnimation();
} else if (f.getAnimator() != null) {
Animator animator = f.getAnimator();
f.setAnimator(null);
animator.cancel();
}
}
if (f.getAnimatingAway() != null || f.getAnimator() != null) {
// We are waiting for the fragment's view to finish
// animating away. Just make a note of the state
// the fragment now should move to once the animation
// is done.
f.setStateAfterAnimating(newState);
newState = Fragment.CREATED;
} else {
if (DEBUG) Log.v(TAG, "movefrom CREATED: " + f);
boolean beingRemoved = f.mRemoving && !f.isInBackStack();
if (beingRemoved || mNonConfig.shouldDestroy(f)) {
boolean shouldClear;
if (mHost instanceof ViewModelStoreOwner) {
shouldClear = mNonConfig.isCleared();
} else if (mHost.getContext() instanceof Activity) {
Activity activity = (Activity) mHost.getContext();
shouldClear = !activity.isChangingConfigurations();
} else {
shouldClear = true;
}
if (beingRemoved || shouldClear) {
mNonConfig.clearNonConfigState(f);
}
f.performDestroy();
dispatchOnFragmentDestroyed(f, false);
} else {
f.mState = Fragment.INITIALIZING;
}
f.performDetach();
dispatchOnFragmentDetached(f, false);
if (!keepActive) {
if (beingRemoved || mNonConfig.shouldDestroy(f)) {
makeInactive(f);
} else {
f.mHost = null;
f.mParentFragment = null;
f.mFragmentManager = null;
if (f.mTargetWho != null) {
Fragment target = mActive.get(f.mTargetWho);
if (target != null && target.getRetainInstance()) {
// Only keep references to other retained Fragments
// to avoid developers accessing Fragments that
// are never coming back
f.mTarget = target;
}
}
}
}
}
}
}
}
if (f.mState != newState) {
Log.w(TAG, "moveToState: Fragment state for " + f + " not updated inline; "
+ "expected state " + newState + " found " + f.mState);
f.mState = newState;
}
}
OP_REMOVE操作会把指定的fragment从FragmentManagerImpl中移除,移除过程中会视配置情况进行状态保存、移除view、释放fragment、FragmentManagerImpl调度其他fragment等处理。
通过调用FragmentTransaction的replace方法,传入指定的布局容器ID和fragment,达到替换布局容器中的fragment的view。
[FragmentTransaction.java]
public FragmentTransaction replace(@IdRes int containerViewId, @NonNull Fragment fragment,
@Nullable String tag) {
// 必须指定布局容器ID
if (containerViewId == 0) {
throw new IllegalArgumentException("Must use non-zero containerViewId");
}
doAddOp(containerViewId, fragment, tag, OP_REPLACE);
return this;
}
添加OP_REPLACE类型的Op到mOps集合中。
接着看执行命令操作的方法executeOpsTogether:
[FragmentManagerImpl.java]
private void executeOpsTogether(ArrayList<BackStackRecord> records,
ArrayList<Boolean> isRecordPop, int startIndex, int endIndex) {
// ···
for (int recordNum = startIndex; recordNum < endIndex; recordNum++) {
final BackStackRecord record = records.get(recordNum);
final boolean isPop = isRecordPop.get(recordNum);
if (!isPop) {
// 根据操作类型进行展开操作
oldPrimaryNav = record.expandOps(mTmpAddedFragments, oldPrimaryNav);
} else {
oldPrimaryNav = record.trackAddedFragmentsInPop(mTmpAddedFragments, oldPrimaryNav);
}
addToBackStack = addToBackStack || record.mAddToBackStack;
}
// ···
// 执行操作
executeOps(records, isRecordPop, startIndex, endIndex);
// ···
}
该方法中再执行命令操作前会先调用BackStackRecord的expandOps方法中根据操作类型进行展开操作。
[BackStackRecord.java]
Fragment expandOps(ArrayList<Fragment> added, Fragment oldPrimaryNav) {
// 遍历mOps集合中的Op
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;
// 标记该fragment是否添加过
boolean alreadyAdded = false;
// 遍历FragmentManagerImpl的mAdded中的Fragment
for (int i = added.size() - 1; i >= 0; i--) {
final Fragment old = added.get(i);
// 判断是否指定过相同的布局容器ID
if (old.mContainerId == containerId) {
// 判断指定了相同布局容器的那个fragment是否就是这个fragment
if (old == f) {
// 标记为true
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;
}
// 创建OP_REMOVE的操作
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中
mOps.add(opNum, removeOp);
// 移除指定的布局容器中的那个fragment
added.remove(old);
opNum++;
}
}
}
if (alreadyAdded) {
// 若该fragment已经添加了,移除这个操作即可
mOps.remove(opNum);
opNum--;
} else {
// 将这个操作的类型修改成OP_ADD
op.mCmd = OP_ADD;
// 将fragment添加进mAdded中
added.add(f);
}
}
break;
case OP_SET_PRIMARY_NAV: {
// ···
}
break;
}
}
return oldPrimaryNav;
}
可以看到OP_REPLACE操作其实是调整为OP_REMOVE+OP_ADD。
通过FragmentTransaction的hide和show方法,可以将指定的fragment隐藏和显示。
[FragmentTransaction.java]
public FragmentTransaction hide(@NonNull Fragment fragment) {
addOp(new Op(OP_HIDE, fragment));
return this;
}
public FragmentTransaction show(@NonNull Fragment fragment) {
addOp(new Op(OP_SHOW, fragment));
return this;
}
添加OP_HIDE或OP_SHOW类型的命令。
接着看处理的部分,在executeOps方法的OP_HIDE case和OP_SHOW case中,会调用FragmentManagerImpl的hideFragment和showFragment方法:
[FragmentManagerImpl.java]
public void hideFragment(Fragment fragment) {
if (DEBUG) Log.v(TAG, "hide: " + fragment);
if (!fragment.mHidden) {
// 将mHidden成员标记为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;
}
}
public void showFragment(Fragment fragment) {
if (DEBUG) Log.v(TAG, "show: " + fragment);
if (fragment.mHidden) {
// 将mHidden成员标记为false
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;
}
}
Fragment中是通过mHidden成员来标记当前是要隐藏还是要显示。
接下来在FragmentManagerImpl的moveToState方法中,会根据mHidden值来设置view的可见:
[FragmentManagerImpl.java]
void moveToState(Fragment f, int newState, int transit, int transitionStyle,
boolean keepActive) {
// ···
if (f.mState <= newState) {
// ···
switch (f.mState) {
// ···
case Fragment.CREATED:
// We want to unconditionally run this anytime we do a moveToState that
// moves the Fragment above INITIALIZING, including cases such as when
// we move from CREATED => CREATED as part of the case fall through above.
if (newState > Fragment.INITIALIZING) {
// 该处理从xml文件中添加Fragment
ensureInflatedFragmentView(f);
}
if (newState > Fragment.CREATED) {
if (DEBUG) Log.v(TAG, "moveto ACTIVITY_CREATED: " + f);
if (!f.mFromLayout) {
ViewGroup container = null;
if (f.mContainerId != 0) {
if (f.mContainerId == View.NO_ID) {
throwException(new IllegalArgumentException(
"Cannot create fragment "
+ f
+ " for a container view with no id"));
}
container = (ViewGroup) mContainer.onFindViewById(f.mContainerId);
if (container == null && !f.mRestored) {
String resName;
try {
resName = f.getResources().getResourceName(f.mContainerId);
} catch (Resources.NotFoundException e) {
resName = "unknown";
}
throwException(new IllegalArgumentException(
"No view found for id 0x"
+ Integer.toHexString(f.mContainerId) + " ("
+ resName
+ ") for fragment " + f));
}
}
f.mContainer = container;
f.performCreateView(f.performGetLayoutInflater(
f.mSavedFragmentState), container, f.mSavedFragmentState);
if (f.mView != null) {
f.mInnerView = f.mView;
f.mView.setSaveFromParentEnabled(false);
if (container != null) {
container.addView(f.mView);
}
// 在创建完view后,判断mHidden是否为true
if (f.mHidden) {
// 设置view为GONE
f.mView.setVisibility(View.GONE);
}
f.onViewCreated(f.mView, f.mSavedFragmentState);
dispatchOnFragmentViewCreated(f, f.mView, f.mSavedFragmentState,
false);
// Only animate the view if it is visible. This is done after
// dispatchOnFragmentViewCreated in case visibility is changed
f.mIsNewlyAdded = (f.mView.getVisibility() == View.VISIBLE)
&& f.mContainer != null;
} else {
f.mInnerView = null;
}
}
f.performActivityCreated(f.mSavedFragmentState);
dispatchOnFragmentActivityCreated(f, f.mSavedFragmentState, false);
if (f.mView != null) {
f.restoreViewState(f.mSavedFragmentState);
}
f.mSavedFragmentState = null;
}
// ···
}
} else if (f.mState > newState) {
// ···
}
// ···
}
void ensureInflatedFragmentView(Fragment f) {
if (f.mFromLayout && !f.mPerformedCreateView) {
f.performCreateView(f.performGetLayoutInflater(
f.mSavedFragmentState), null, f.mSavedFragmentState);
if (f.mView != null) {
f.mInnerView = f.mView;
f.mView.setSaveFromParentEnabled(false);
// 若mHidden为true,则将view设置为GONE
if (f.mHidden) f.mView.setVisibility(View.GONE);
f.onViewCreated(f.mView, f.mSavedFragmentState);
dispatchOnFragmentViewCreated(f, f.mView, f.mSavedFragmentState, false);
} else {
f.mInnerView = null;
}
}
}
若mHidden设置为true,则会将通过Fragment创建的view的可见属性设置为GONE。
回到FragmentManagerImpl的moveFragmentToExpectedState方法:
[FragmentManagerImpl.java]
void moveFragmentToExpectedState(Fragment f) {
// ···
moveToState(f, nextState, f.getNextTransition(), f.getNextTransitionStyle(), false);
// ···
// mHiddenChanged默认为false,当对fragment进行显示隐藏操作变化时会变为true
if (f.mHiddenChanged) {
completeShowHideFragment(f);
}
}
该方法中在执行完moveToState方法将fragment调整到最终目标状态后,在该方法的结尾会判断调用completeShowHideFragment方法,进入这个方法看看做了什么动作:
[FragmentManagerImpl.java]
void completeShowHideFragment(final Fragment fragment) {
// 判断该fragment中是否有创建view
if (fragment.mView != null) {
AnimationOrAnimator anim = loadAnimation(fragment, fragment.getNextTransition(),
!fragment.mHidden, fragment.getNextTransitionStyle());
// 判断是否设置了Animator
if (anim != null && anim.animator != null) {
anim.animator.setTarget(fragment.mView);
// 判断该fragment是否隐藏
if (fragment.mHidden) {
// isHideReplaced方法判断是否正在进行隐藏的过渡动画中
if (fragment.isHideReplaced()) {
// 正在进行隐藏的过渡动画
fragment.setHideReplaced(false);
} else {
// 设置进行隐藏的过渡动画
final ViewGroup container = fragment.mContainer;
final View animatingView = fragment.mView;
container.startViewTransition(animatingView);
// Delay the actual hide operation until the animation finishes,
// otherwise the fragment will just immediately disappear
anim.animator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
container.endViewTransition(animatingView);
animation.removeListener(this);
if (fragment.mView != null && fragment.mHidden) {
fragment.mView.setVisibility(View.GONE);
}
}
});
}
} else {
// 若为显示,则将fragment的view设置为VISIBLE
fragment.mView.setVisibility(View.VISIBLE);
}
anim.animator.start();
} else {
if (anim != null) {
// 未设置Animator,但设置了Animation
fragment.mView.startAnimation(anim.animation);
anim.animation.start();
}
final int visibility = fragment.mHidden && !fragment.isHideReplaced()
? View.GONE
: View.VISIBLE;
// 设置fragment的view的可见属性
fragment.mView.setVisibility(visibility);
if (fragment.isHideReplaced()) {
fragment.setHideReplaced(false);
}
}
}
if (fragment.mAdded && isMenuAvailable(fragment)) {
mNeedMenuInvalidate = true;
}
// 把mHiddenChanged成员置回false
fragment.mHiddenChanged = false;
// 回调onHiddenChanged方法
fragment.onHiddenChanged(fragment.mHidden);
}
该方法中逻辑主要是过渡动画和view可见属性的设置。
前文大致跟踪了一个Fragment从新建到添加入FragmentActivity的过程。
首先FragmentManager将“添加Fragment”的行为封装成一个Op操作,再将Op加入一个事务BackStackRecord,然后将事务加入待执行队列保存,之后通过Handler调度至主线程执行。
接着FragmentManager从遍历待执行队列中的事务,依次执行。执行过程中根据操作类型以及Fragment状态和FragmentManager状态,执行Fragment对应阶段的处理和生命周期回调。