基本使用
Fragment的使用一般涉及到两个类:FragmentManager和FragmentTransaction。
val fragmentManager = supportFragmentManager
val fragmentTransaction = fragmentManager.beginTransaction()
可使用 FragmentManager
执行的操作包括:
- 通过
findFragmentById()
或findFragmentByTag()
获取 Activity 中存在的片段。 - 通过
popBackStack()
(模拟用户发出的返回命令)使片段从返回栈中弹出。 - 通过
addOnBackStackChangedListener()
注册侦听返回栈变化的侦听器。
可以从 FragmentManager
获取一个 FragmentTransaction
实例,然后使用 add()
、remove()
和 replace()
等方法,为给定事务设置您想要执行的所有更改。然后,如要将事务应用到 Activity,您必须调用 commit()
。
val newFragment = ExampleFragment()
val transaction = supportFragmentManager.beginTransaction()
transaction.replace(R.id.fragment_container, newFragment)
transaction.addToBackStack(null)
transaction.commit()
源码分析
FragmentController
MainActivity:AppCompatActivity:FragmentActivity。在FragmentActivity中有一个常量叫mFragments。
final FragmentController mFragments = FragmentController.createController(new HostCallbacks());
这是一个FragmentController对象。FragmentController,听名字是一个控制类,看来应该是用来控制Fragment的,其内部持有一个FragmentHostCallback类型的对象mHost。
public class FragmentController {
private final FragmentHostCallback<?> mHost;
...
//下面都是类似这样的代码:
public XX FunXX () {
return mHost.mFragmentManager.FunXX();
}
//比如:
public void attachHost(@Nullable Fragment parent) {
mHost.mFragmentManager.attachController(mHost, mHost /*container*/, parent);
}
}
扫一眼这个控制类下面的方法,基本上都是调用的mHost.mFragmentManager.XX( )
方法,所以我们判断FragmentController类又是个空壳子,其类目的方法全在mHost的mFragmentManager对象中实现。
所以我们理所当然的打开FragmentHostCallback,发现里面持有这样几个对象。
public abstract class FragmentHostCallback<E> extends FragmentContainer {
private final Activity mActivity;
private final Context mContext;
private final Handler mHandler;
private final int mWindowAnimations;
final FragmentManager mFragmentManager = new FragmentManagerImpl();
...
}
FragmentManager是个常量,我们没有调用任何代码ta就在这里自己创建了。得到这个信息就够了,然后我们看自己调用的代码。
wait...
对了,还有一个地方要看一眼,在FragmentActivity的onCreate方法中,有一行mFragments.attachHost(null /parent/)**;去到FragmentManager中看:
void attachController(@NonNull FragmentHostCallback<?> host,
@NonNull FragmentContainer container, @Nullable final Fragment parent) {
if (mHost != null) throw new IllegalStateException("Already attached");
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
if (host instanceof OnBackPressedDispatcherOwner) {
OnBackPressedDispatcherOwner dispatcherOwner = ((OnBackPressedDispatcherOwner) host);
mOnBackPressedDispatcher = dispatcherOwner.getOnBackPressedDispatcher();
LifecycleOwner owner = parent != null ? parent : dispatcherOwner;
mOnBackPressedDispatcher.addCallback(owner, mOnBackPressedCallback);
}
// Get the FragmentManagerViewModel
if (parent != null) {
mNonConfig = parent.mFragmentManager.getChildNonConfig(parent);
} else if (host instanceof ViewModelStoreOwner) {
ViewModelStore viewModelStore = ((ViewModelStoreOwner) host).getViewModelStore();
mNonConfig = FragmentManagerViewModel.getInstance(viewModelStore);
} else {
mNonConfig = new FragmentManagerViewModel(false);
}
}
给FragmentManager传了一些值进去,包括mHost,mParent等。mHost就是FragmentHostCallback。
FragmentManager
好了,现在我们自己在调用getSupportFragmentManager()方法时,返回的就是我们刚刚看到的mFragmentManager,也是创建FragmentControl时带入的HostCallbacks。
//-----------FragmentActivity.java-------------
public FragmentManager getSupportFragmentManager() {
return mFragments.getSupportFragmentManager();
}
//-----------FragmentControl.java-----------------
public FragmentManager getSupportFragmentManager() {
return mHost.mFragmentManager;
}
所以beginTransaction自然要去FragmentManager类下面去找了。
beginTransaction
public FragmentTransaction beginTransaction() {
return new BackStackRecord(this);//this就是FragmentManager呐。
}
BackStackRecord继承FragmentTransaction,FragmentTransaction是一个抽象类。
final class BackStackRecord extends FragmentTransaction implements FragmentManager.BackStackEntry, FragmentManager.OpGenerator {
...
}
所以我们一般调用add、show、hide、replace等操作时,实际是调用的FragmentTransaction中的方法。以add方法为例:
add(containerViewId,fragment)
public abstract class FragmentTransaction {
public FragmentTransaction add(@IdRes int containerViewId, @NonNull Fragment fragment) {
doAddOp(containerViewId, fragment, null, OP_ADD);
return this;
}
void doAddOp(int containerViewId, Fragment fragment, @Nullable String tag, int opcmd) {
final Class<?> fragmentClass = fragment.getClass();
final int modifiers = fragmentClass.getModifiers();
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) {
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;
}
//---------------------存储containerViewId到fragment中--------------
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");
}
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;
}
addOp(new Op(opcmd, fragment));
}
ArrayList<Op> mOps = new ArrayList<>();
void addOp(Op op) {
mOps.add(op);
op.mEnterAnim = mEnterAnim;
op.mExitAnim = mExitAnim;
op.mPopEnterAnim = mPopEnterAnim;
op.mPopExitAnim = mPopExitAnim;
}
public abstract int commit();
}
校验完合法性后,做了两件事:
将containerViewId存入到fragment中的mContainerId 和 mFragmentId;
addOp()传入的是一个Op对象,包含标记opcmd和fragment。op对象随后被添加到一个叫mOps的队列中。
看来关键代码在commit身上,所以我们每次用Fragment的时候忘记调用commit就会看不到界面变化。
commit
commit是个抽象方法,其实现在BackStackRecord中:
final class BackStackRecord extends FragmentTransaction implements FragmentManager.BackStackEntry, FragmentManager.OpGenerator {
@Override
public int commit() {
return commitInternal(false);
}
int commitInternal(boolean allowStateLoss) {
if (mCommitted) throw new IllegalStateException("commit already called");
if (FragmentManager.isLoggingEnabled(Log.VERBOSE)) {
Log.v(TAG, "Commit: " + this);
LogWriter logw = new LogWriter(TAG);
PrintWriter pw = new PrintWriter(logw);
dump(" ", pw);
pw.close();
}
mCommitted = true;
if (mAddToBackStack) {
mIndex = mManager.allocBackStackIndex();
} else {
mIndex = -1;
}
mManager.enqueueAction(this, allowStateLoss);
return mIndex;
}
}
mAddToBackStack表示是否加入返回栈,是的话就从manager中返回一个index,表示当前栈中第几个fragment,否则返回-1。
重点方法在enqueueAction中:
enqueueAction
private final ArrayList<OpGenerator> mPendingActions = new ArrayList<>();
void enqueueAction(@NonNull OpGenerator action, boolean allowStateLoss) {
if (!allowStateLoss) {
//不允许状态改变
if (mHost == null) {
if (mDestroyed) {
throw new IllegalStateException("FragmentManager has been destroyed");
} else {
throw new IllegalStateException("FragmentManager has not been attached to a "
+ "host.");
}
}
checkStateLoss();//如果已经改变,就在在这个方法内抛错
}
synchronized (mPendingActions) {
if (mHost == null) {
if (allowStateLoss) {
// This FragmentManager isn't attached, so drop the entire transaction.
return;
}
throw new IllegalStateException("Activity has been destroyed");
}
mPendingActions.add(action);
scheduleCommit();
}
}
void scheduleCommit() {
synchronized (mPendingActions) {
boolean postponeReady =
mPostponedTransactions != null && !mPostponedTransactions.isEmpty();
boolean pendingReady = mPendingActions.size() == 1;
if (postponeReady || pendingReady) {
mHost.getHandler().removeCallbacks(mExecCommit);
mHost.getHandler().post(mExecCommit);
updateOnBackPressedCallbackEnabled();
}
}
}
private Runnable mExecCommit = new Runnable() {
@Override
public void run() {
execPendingActions(true);
}
};
做了三件事:1. 如果不允许状态改变则要做一些检查;
将action加入mPendingActions队列中;
-
scheduleCommit:
3.1 (校验判断后)通过Handler将mExecCommit发送出去;
3.2 处理是否拦截返回事件相关事务【通过返回栈的数目等信息判断】
我们在一开始的时候提到FragmentActivity的onCreate方法中有用到Manager.attachController(),mHost就是传进来的FragmentHostCallback对象。而mHandle是在其构造方法中就已被创建了。
这里用Handle是为了切换到主线程。我们直接关注mExecCommit中的execPendingActions方法就好:
execPendingActions
boolean execPendingActions(boolean allowStateLoss) {
//准备操作,初始化mTmpRecords,mTmpIsPop等
ensureExecReady(allowStateLoss);
boolean didSomething = false;
while (generateOpsForPendingActions(mTmpRecords, mTmpIsPop)) {
mExecutingActions = true;
try {
removeRedundantOperationsAndExecute(mTmpRecords, mTmpIsPop);
} finally {
cleanupExec();
}
didSomething = true;
}
updateOnBackPressedCallbackEnabled();
doPendingDeferredStart();
mFragmentStore.burpActive();
return didSomething;
}
generateOpsForPendingActions 循环条件
首先看while中的generateOpsForPendingActions:其大致做的事是,遍历完mPendingActions数组,为数组中每个OpGenerator执行generateOps方法。然后清空数组。操作成功返回true,否则【包括数组为null的情况】返回false,
private boolean generateOpsForPendingActions(@NonNull ArrayList<BackStackRecord> records,
@NonNull ArrayList<Boolean> isPop) {
boolean didSomething = false;
synchronized (mPendingActions) {
if (mPendingActions.isEmpty()) {
return false;
}
final int numActions = mPendingActions.size();
for (int i = 0; i < numActions; i++) {
didSomething |= mPendingActions.get(i).generateOps(records, isPop);
}
mPendingActions.clear();
mHost.getHandler().removeCallbacks(mExecCommit);
}
return didSomething;
}
而在generateOps方法中,分别向records和isRecordPop中填充元素。
//----------------------BackStackRecord.java下--------------
@Override
public boolean generateOps(@NonNull ArrayList<BackStackRecord> records,
@NonNull ArrayList<Boolean> isRecordPop) {
if (FragmentManager.isLoggingEnabled(Log.VERBOSE)) {
Log.v(TAG, "Run: " + this);
}
records.add(this);
isRecordPop.add(false);
if (mAddToBackStack) {
mManager.addBackStackState(this);
}
return true;
}
综上,整个generateOpsForPendingActions的作用就是将mPendingActions中所有的记录<BackStackRecord>添加到了records数组中。
removeRedundantOperationsAndExecute 循环内部
再看循环内部的removeRedundantOperationsAndExecute方法。先猜想一波,刚刚向数组中添加了元素,现在应该操作这些元素了。
//之前的版本中这个方法名叫 optimizeAndExecuteOps
private void removeRedundantOperationsAndExecute(@NonNull ArrayList<BackStackRecord> records,
@NonNull ArrayList<Boolean> isRecordPop) {
if (records.isEmpty()) {
return;
}
if (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:
//强制启动所有 与计划的transactions交互的 延迟的 transactions。即完成以前已延迟但现在已准备好的事务的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++;
}
}
executeOpsTogether(records, isRecordPop, recordNum, reorderingEnd);
startIndex = reorderingEnd;
recordNum = reorderingEnd - 1;
}
}
if (startIndex != numRecords) {
// 开启操作排序优化情况下可能会满足该if条件
executeOpsTogether(records, isRecordPop, startIndex, numRecords);
}
}
之前的版本中这个方法名叫 optimizeAndExecuteOps【优化并执行】,现在叫removeRedundantOperationsAndExecute【删除冗余操作并执行】。从命名可以看出Google开发团队对这个方法做出的解释--当有多个待执行事务时,FragmentManager会删除部分冗余事务操作。例如:
- 假设有两个事务对同一布局容器一起执行,一个事务添加了一个 Fragment A,下一个事务将其替换为 Fragment B。则优化后会将第一个操作取消,仅添加 Fragment B。
- 假设有三个事务,一个事务添加了 Fragment A,第二个事务添加了 Fragment B,然后第三个删除了 Fragment A。那么优化后将不会执行 Fragment A的添加和删除,仅添加 Fragment B。
排序优化操作会导致出现超出开发者预期的行为,因此默认不进行此操作。
实际实现的代码时executeOpsTogether()方法。
private void executeOpsTogether(@NonNull ArrayList<BackStackRecord> records,
@NonNull ArrayList<Boolean> isRecordPop, int startIndex, int endIndex) {
final boolean allowReordering = records.get(startIndex).mReorderingAllowed;
boolean addToBackStack = false;
if (mTmpAddedFragments == null) {
mTmpAddedFragments = new ArrayList<>();
} else {
mTmpAddedFragments.clear();
}
mTmpAddedFragments.addAll(mFragmentStore.getFragments());
Fragment oldPrimaryNav = getPrimaryNavigationFragment();
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;
}
mTmpAddedFragments.clear();
if (!allowReordering) {
FragmentTransition.startTransitions(this, records, isRecordPop, startIndex, endIndex,
false, mFragmentTransitionCallback);
}
executeOps(records, isRecordPop, startIndex, endIndex);
int postponeIndex = endIndex;
if (allowReordering) {
ArraySet<Fragment> addedFragments = new ArraySet<>();
addAddedFragments(addedFragments);
postponeIndex = postponePostponableTransactions(records, isRecordPop,
startIndex, endIndex, addedFragments);
makeRemovedFragmentsInvisible(addedFragments);
}
if (postponeIndex != startIndex && allowReordering) {
// need to run something now
FragmentTransition.startTransitions(this, records, isRecordPop, startIndex,
postponeIndex, true, mFragmentTransitionCallback);
moveToState(mCurState, true);
}
for (int recordNum = startIndex; recordNum < endIndex; recordNum++) {
final BackStackRecord record = records.get(recordNum);
final boolean isPop = isRecordPop.get(recordNum);
if (isPop && record.mIndex >= 0) {
record.mIndex = -1;
}
record.runOnCommitRunnables();
}
if (addToBackStack) {
reportBackStackChanged();
}
}
executeOps(records, isRecordPop, startIndex, endIndex);
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);
// Only execute the add operations at the end of
// all transactions.
boolean moveToState = i == (endIndex - 1);
record.executePopOps(moveToState);
} else {
record.bumpBackStackNesting(1);
record.executeOps();
}
}
}
record.executeOps()
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);
}
switch (op.mCmd) {
case OP_ADD:
f.setNextAnim(op.mEnterAnim);
mManager.setExitAnimationOrder(f, false);
mManager.addFragment(f);
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.setExitAnimationOrder(f, false);
mManager.showFragment(f);
break;
case OP_DETACH:
f.setNextAnim(op.mExitAnim);
mManager.detachFragment(f);
break;
case OP_ATTACH:
f.setNextAnim(op.mEnterAnim);
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);
}
if (!mReorderingAllowed && op.mCmd != OP_ADD && f != null) {
mManager.moveFragmentToExpectedState(f);
}
}
if (!mReorderingAllowed) {
// Added fragments are added at the end to comply with prior behavior.
mManager.moveToState(mManager.mCurState, true);
}
}
在这里根据不同的命令,执行不同的操作。最后MoveToState。
MoveToState(int,boolean)
void moveToState(int newState, boolean always) {
if (mHost == null && newState != Fragment.INITIALIZING) {
throw new IllegalStateException("No activity");
}
if (!always && newState == mCurState) {
return;
}
mCurState = newState;
// Must add them in the proper order. mActive fragments may be out of order
for (Fragment f : mFragmentStore.getFragments()) {
moveFragmentToExpectedState(f);
}
// Now iterate through all active fragments. These will include those that are removed
// and detached.
for (Fragment f : mFragmentStore.getActiveFragments()) {
if (f != null && !f.mIsNewlyAdded) {
moveFragmentToExpectedState(f);
}
}
startPendingDeferredFragments();
if (mNeedMenuInvalidate && mHost != null && mCurState == Fragment.RESUMED) {
mHost.onSupportInvalidateOptionsMenu();
mNeedMenuInvalidate = false;
}
}
最终把Fragment展示出来实现的方法是moveFragemtnTOExpectedState(f);
void moveFragmentToExpectedState(@NonNull Fragment f) {
if (!mFragmentStore.containsActiveFragment(f.mWho)) {
if (isLoggingEnabled(Log.DEBUG)) {
Log.d(TAG, "Ignoring moving " + f + " to state " + mCurState
+ "since it is not added to " + this);
}
return;
}
moveToState(f);
if (f.mView != null) {
// Move the view if it is out of order
Fragment underFragment = mFragmentStore.findFragmentUnder(f);
if (underFragment != null) {
final View underView = underFragment.mView;
// make sure this fragment is in the right order.
final 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) {
// Make it visible and run the animations
if (f.mPostponedAlpha > 0f) {
f.mView.setAlpha(f.mPostponedAlpha);
}
f.mPostponedAlpha = 0f;
f.mIsNewlyAdded = false;
// run animations:
FragmentAnim.AnimationOrAnimator anim = FragmentAnim.loadAnimation(
mHost.getContext(), mContainer, f, true);
if (anim != null) {
if (anim.animation != null) {
f.mView.startAnimation(anim.animation);
} else {
anim.animator.setTarget(f.mView);
anim.animator.start();
}
}
}
}
if (f.mHiddenChanged) {
completeShowHideFragment(f);
}
}
void moveToState(@NonNull Fragment f) {
moveToState(f, mCurState);
}
跟着这个moveToState(Fragment,int)才是主角:在生命周期的每个阶段要做什么,都写的很清楚。
void moveToState(@NonNull Fragment f, int newState) {
FragmentStateManager fragmentStateManager = mFragmentStore.getFragmentStateManager(f.mWho);
if (fragmentStateManager == null) {
// Ideally, we only call moveToState() on active Fragments. However,
// in restoreSaveState() we can call moveToState() on retained Fragments
// just to clean them up without them ever being added to mActive.
// For these cases, a brand new FragmentStateManager is enough.
fragmentStateManager = new FragmentStateManager(mLifecycleCallbacksDispatcher, f);
// Only allow this FragmentStateManager to go up to CREATED at the most
fragmentStateManager.setFragmentManagerState(Fragment.CREATED);
}
newState = Math.min(newState, fragmentStateManager.computeMaxState());
if (f.mState <= newState) {
// If we are moving to the same state, we do not need to give up on the animation.
if (f.mState < newState && !mExitAnimationCancellationSignals.isEmpty()) {
// The fragment is currently being animated... but! Now we
// want to move our state back up. Give up on waiting for the
// animation and proceed from where we are.
cancelExitAnimation(f);
}
switch (f.mState) {
case Fragment.INITIALIZING:
if (newState > Fragment.INITIALIZING) {
if (isLoggingEnabled(Log.DEBUG)) Log.d(TAG, "moveto ATTACHED: " + f);
// 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.
if (f.mTarget != null) {
if (!f.mTarget.equals(findActiveFragment(f.mTarget.mWho))) {
throw new IllegalStateException("Fragment " + f
+ " declared target fragment " + f.mTarget
+ " that does not belong to this FragmentManager!");
}
if (f.mTarget.mState < Fragment.CREATED) {
moveToState(f.mTarget, Fragment.CREATED);
}
f.mTargetWho = f.mTarget.mWho;
f.mTarget = null;
}
if (f.mTargetWho != null) {
Fragment target = findActiveFragment(f.mTargetWho);
if (target == null) {
throw new IllegalStateException("Fragment " + f
+ " declared target fragment " + f.mTargetWho
+ " that does not belong to this FragmentManager!");
}
if (target.mState < Fragment.CREATED) {
moveToState(target, Fragment.CREATED);
}
}
fragmentStateManager.attach(mHost, this, mParent);
}
// fall through
case Fragment.ATTACHED:
if (newState > Fragment.ATTACHED) {
fragmentStateManager.create();
}
// fall through
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) {
fragmentStateManager.ensureInflatedView();
}
if (newState > Fragment.CREATED) {
fragmentStateManager.createView(mContainer);
fragmentStateManager.activityCreated();
fragmentStateManager.restoreViewState();
}
// fall through
case Fragment.ACTIVITY_CREATED:
if (newState > Fragment.ACTIVITY_CREATED) {
fragmentStateManager.start();
}
// fall through
case Fragment.STARTED:
if (newState > Fragment.STARTED) {
fragmentStateManager.resume();
}
}
} else if (f.mState > newState) {
....
}
if (f.mState != newState) {
if (isLoggingEnabled(Log.DEBUG)) {
Log.d(TAG, "moveToState: Fragment state for " + f + " not updated inline; "
+ "expected state " + newState + " found " + f.mState);
}
f.mState = newState;
}
}
所以就会按顺序执行FragmentStateManager的attach--create---createView--activityCreated--start--resume方法。
以FragmentManager中的attach方法和create方法为例:
FragementManager-attach/create
void attach(@NonNull FragmentHostCallback<?> host, @NonNull FragmentManager fragmentManager,
@Nullable Fragment parentFragment) {
mFragment.mHost = host;
mFragment.mParentFragment = parentFragment;
mFragment.mFragmentManager = fragmentManager;
mDispatcher.dispatchOnFragmentPreAttached(
mFragment, host.getContext(), false);
mFragment.performAttach();
if (mFragment.mParentFragment == null) {
host.onAttachFragment(mFragment);
} else {
mFragment.mParentFragment.onAttachFragment(mFragment);
}
mDispatcher.dispatchOnFragmentAttached(
mFragment, host.getContext(), false);
}
void create() {
if (FragmentManager.isLoggingEnabled(Log.DEBUG)) {
Log.d(TAG, "moveto CREATED: " + mFragment);
}
if (!mFragment.mIsCreated) {
mDispatcher.dispatchOnFragmentPreCreated(
mFragment, mFragment.mSavedFragmentState, false);
mFragment.performCreate(mFragment.mSavedFragmentState);
mDispatcher.dispatchOnFragmentCreated(
mFragment, mFragment.mSavedFragmentState, false);
} else {
mFragment.restoreChildFragmentState(mFragment.mSavedFragmentState);
mFragment.mState = Fragment.CREATED;
}
}
最后会调用到performAttach/performCreate方法:
void performAttach() {
mChildFragmentManager.attachController(mHost, new FragmentContainer() {
@Override
@Nullable
public View onFindViewById(int id) {
if (mView == null) {
throw new IllegalStateException("Fragment " + this + " does not have a view");
}
return mView.findViewById(id);
}
@Override
public boolean onHasView() {
return (mView != null);
}
}, this);
mState = ATTACHED;
mCalled = false;
onAttach(mHost.getContext());
if (!mCalled) {
throw new SuperNotCalledException("Fragment " + this
+ " did not call through to super.onAttach()");
}
}
void performCreate(Bundle savedInstanceState) {
mChildFragmentManager.noteStateNotSaved();
mState = CREATED;
mCalled = false;
mSavedStateRegistryController.performRestore(savedInstanceState);
onCreate(savedInstanceState);
mIsCreated = true;
if (!mCalled) {
throw new SuperNotCalledException("Fragment " + this
+ " did not call through to super.onCreate()");
}
mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);
}
最后终于调用到了我们自己重写的的onAttach/onCreate方法里面。