AndroidX Fragment探究-生命周期
文章目录
概述
Fragment的生命周期依托FragmentActivity管理调度,在FragmentActivity的各个生命周期方法回调中,会将对应生命状态派发给依附于FragmentActivity的所有Fragment。
源码探究
文中源码基于’androidx.fragment:fragment:1.1.0’
Fragment的生命周期派发
上图为FragmentActivity和Fragment的生命周期对照,随着FragmentActivity的生命周期变化,也会调整Fragment的生命周期状态。
FragmentActivity首先会设置FragmentManagerImpl中的生命状态,再通过FragmentManagerImpl来更新其中的Fragment的状态。
状态常量值
在Fragment类中定义了5个状态常量值,用于标记当前状态:
- INITIALIZING(0):初始状态、默认状态,和图2中onDestroy状态
- CREATED(1):对应图2中Created、onDestroyView状态
- ACTIVITY_CREATED(2):对应图2中onActivityCreated至Started、Stopped状态
- STARTED(3):对应图2中Started、Paused状态
- RESUMED(4):对应图2中Resumed状态
FragmentManagerImpl利用mCurState成员变量来标记当前状态,Fragment利用mState成员变量来标记当前状态。
更新FragmentManagerImpl的生命周期状态
这里以FragmentActivity的生命周期回调开始,先看派发给FragmentManagerImpl各个状态的时机。
onCreate
[FragmentActivity.java]
protected void onCreate(@Nullable Bundle savedInstanceState) {
// 进行上下文绑定,FragmentManagerImpl会持有HostCallbacks引用
mFragments.attachHost(null /*parent*/);
// 省略savedInstanceState部分 ···
// 省略mPendingFragmentActivityResults部分 ···
super.onCreate(savedInstanceState);
// 省略LifecycleRegistry部分 ···
// 通过FragmentController来调用FragmentManagerImpl
mFragments.dispatchCreate();
}
FragmentActivity中调用FragmentManagerImpl的相关方法都是通过FragmentController来间接调用。
继续看dispatchCreate方法:
[FragmentController.java]
public void dispatchCreate() {
// 通过FragmentHostCallback来调用FragmentManagerImpl
mHost.mFragmentManager.dispatchCreate();
}
这里最终调用了FragmentManagerImpl的dispatchCreate方法:
[FragmentManagerImpl.java]
public void dispatchCreate() {
// mStateSaved用于标记是否保存Fragment State(通过saveAllState方法保存)
mStateSaved = false;
// mStopped用于标记当前是否Stopped
mStopped = false;
// 传入状态值CREATED
dispatchStateChange(Fragment.CREATED);
}
该方法中调用dispatchStateChange方法并传入CREATED来更新状态。
[FragmentManagerImpl.java]
private void dispatchStateChange(int nextState) {
try {
mExecutingActions = true;
// 变更当前状态为传入的目标状态
moveToState(nextState, false);
} finally {
mExecutingActions = false;
}
// 处理待执行任务队列
execPendingActions();
}
真正更新状态是在moveToState方法中:
[FragmentManagerImpl.java]
void moveToState(int newState, boolean always) {
if (mHost == null && newState != Fragment.INITIALIZING) {
throw new IllegalStateException("No activity");
}
// 检查状态是否相等,always此时传入的为false
if (!always && newState == mCurState) {
return;
}
// 更新状态
mCurState = newState;
// 省略触发Fragment更新状态部分
// ···
}
在该方法中将传入的指定的状态赋值给了mCurState成员,从而达到FragmentManagerImpl的状态更新。
onStart
[FragmentActivity.java]
protected void onStart() {
super.onStart();
mStopped = false;
// mCreated默认为false
if (!mCreated) {
mCreated = true;
// 派发ACTIVITY_CREATED状态
mFragments.dispatchActivityCreated();
}
mFragments.noteStateNotSaved();
mFragments.execPendingActions();
// NOTE: HC onStart goes here.
mFragmentLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_START);
// 派发STARTED状态
mFragments.dispatchStart();
}
在onStart方法中,判断若是首次调用,则会调用dispatchActivityCreated方法。最后调用dispatchStart方法。这两个方法同dispatchCreate方法一样,通过FragmentController->FragmentHostCallback->FragmentManagerImpl调用对应方法。
[FragmentManagerImpl.java]
public void dispatchActivityCreated() {
mStateSaved = false;
mStopped = false;
// 派发ACTIVITY_CREATED状态
dispatchStateChange(Fragment.ACTIVITY_CREATED);
}
public void dispatchStart() {
mStateSaved = false;
mStopped = false;
// 派发STARTED状态
dispatchStateChange(Fragment.STARTED);
}
前后更新状态为ACTIVITY_CREATED和STARTED。
onPostResume
在Activity的performResume方法中会调用onPostResume方法:
[Activity.java]
final void performResume(boolean followedByPause, String reason) {
// ···
// 将会触发Activity的onResume回调
mInstrumentation.callActivityOnResume(this);
// ···
onPostResume();
// ···
}
而FragmentActivity重写了onPostResume方法:
[FragmentActivity.java]
protected void onPostResume() {
super.onPostResume();
onResumeFragments();
}
protected void onResumeFragments() {
mFragmentLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_RESUME);
// 派发RESUMED状态
mFragments.dispatchResume();
}
dispatchResume方法最终会调用FragmentManagerImpl的dispatchResume方法,将状态更新为RESUMED。
onPause
[FragmentActivity.java]
protected void onPause() {
super.onPause();
mResumed = false;
// 派发STARTED状态
mFragments.dispatchPause();
mFragmentLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_PAUSE);
}
[FragmentManagerImpl.java]
public void dispatchPause() {
dispatchStateChange(Fragment.STARTED);
}
在onPause中,将调用dispatchPause方法,又会将FragmentManagerImpl的状态置为STARTED。
onStop
[FragmentActivity.java]
protected void onStop() {
super.onStop();
mStopped = true;
markFragmentsCreated();
// 派发ACTIVITY_CREATED状态
mFragments.dispatchStop();
mFragmentLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_STOP);
}
[FragmentManagerImpl.java]
public void dispatchStop() {
// 标记Stopped为true
mStopped = true;
dispatchStateChange(Fragment.ACTIVITY_CREATED);
}
在onStop中将会更新FragmentManagerImpl的状态为ACTIVITY_CREATED。
onDestroy
[FragmentActivity.java]
protected void onDestroy() {
super.onDestroy();
mFragments.dispatchDestroy();
mFragmentLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_DESTROY);
}
[FragmentManagerImpl.java]
public void dispatchDestroy() {
mDestroyed = true;
execPendingActions();
// 更新状态为INITIALIZING
dispatchStateChange(Fragment.INITIALIZING);
// 解除引用
mHost = null;
mContainer = null;
mParent = null;
if (mOnBackPressedDispatcher != null) {
// mOnBackPressedDispatcher can hold a reference to the host
// so we need to null it out to prevent memory leaks
mOnBackPressedCallback.remove();
mOnBackPressedDispatcher = null;
}
}
在onDestroy中将会更新FragmentManagerImpl的状态为INITIALIZING。
小结
在FragmentActivity的onCreate回调中将会更新FragmentManagerImpl的状态为CREATED;在onStart回调中,将会更新状态为STARTED;在onPostResume中,更新状态为RESUMED;在onPause中,更新状态为STARTED;在onStop中,更新状态为ACTIVITY_CREATED;在onDestroy中,更新状态为INITIALIZING。
更新Fragment的生命周期状态
FragmentManagerImpl在moveToState方法中更新自身状态后,便会遍历mAdded(保存添加的Fragment的集合),依次取出Fragment,调用moveFragmentToExpectedState方法并传入Fragment。在moveFragmentToExpectedState方法中又会调用另一个moveToState重载方法,在该方法中实现Fragment的生命状态更新。
[FragmentManagerImpl.java]
// 参数f为将要处理的Fragment,newState为将要设置的目标状态
void moveToState(Fragment f, int newState, int transit, int transitionStyle,
boolean keepActive) {
// Fragments that are not currently added will sit in the onCreate() state.
// 判断是否对fragment执行了detach操作
if ((!f.mAdded || f.mDetached) && newState > Fragment.CREATED) {
newState = Fragment.CREATED;
}
// 判断是否对fragment执行了remove操作
if (f.mRemoving && newState > f.mState) {
if (f.mState == Fragment.INITIALIZING && f.isInBackStack()) {
// Allow the fragment to be created so that it can be saved later.
newState = Fragment.CREATED;
} else {
// While removing a fragment, we can't change it to a higher state.
newState = f.mState;
}
}
// Defer start if requested; don't allow it to move to STARTED or higher
// if it's not already started.
// 判断是否延迟启动(可通过setUserVisibleHint设置)
if (f.mDeferStart && f.mState < Fragment.STARTED && newState > Fragment.ACTIVITY_CREATED) {
newState = Fragment.ACTIVITY_CREATED;
}
// Don't allow the Fragment to go above its max lifecycle state
// Ensure that Fragments are capped at CREATED instead of ACTIVITY_CREATED.
// 判断是否超过fragment设置的最大生命周期状态(默认为RESUMED,这里利用Lifecycle组件中的枚举值来比较)
if (f.mMaxState == Lifecycle.State.CREATED) {
newState = Math.min(newState, Fragment.CREATED);
} else {
newState = Math.min(newState, f.mMaxState.ordinal());
}
// ···
}
moveToState方法中第一部分是对目标生命周期状态进行校验和修正,确保状态处于合理的范围内,接下来便会根据目标状态和fragment当前状态(默认INITIALIZING)进行调度。
[FragmentManagerImpl.java]
// 参数f为将要处理的Fragment,newState为将要设置的目标状态
void moveToState(Fragment f, int newState, int transit, int transitionStyle,
boolean keepActive) {
// ···
// fragment当前生命周期状态小等于目标状态,那么会进行从create(假设)到resume(假设)的生长过程
if (f.mState <= newState) {
// For fragments that are created from a layout, when restoring from
// state we don't want to allow them to be created until they are
// being reloaded from the layout.
if (f.mFromLayout && !f.mInLayout) {
// 跳过通过布局xml定义创建的fragment
return;
}
if (f.getAnimatingAway() != null || f.getAnimator() != null) {
// The fragment is currently being animated... but! Now we
// want to move our state back up. Give up on waiting for the
// animation, move to whatever the final state should be once
// the animation is done, and then we can proceed from there.
f.setAnimatingAway(null);
f.setAnimator(null);
// 当前fragment正在进行离开动画,先更新状态至之前保存的动画结束后的目标状态
moveToState(f, f.getStateAfterAnimating(), 0, 0, true);
}
switch (f.mState) {
case Fragment.INITIALIZING:
if (newState > Fragment.INITIALIZING) {
if (DEBUG) Log.v(TAG, "moveto CREATED: " + f);
if (f.mSavedFragmentState != null) {
// 省略mSavedFragmentState部分 ···
}
f.mHost = mHost;
f.mParentFragment = mParent;
f.mFragmentManager = mParent != null
? mParent.mChildFragmentManager : mHost.mFragmentManager;
// 省略Target Fragment部分 ···
dispatchOnFragmentPreAttached(f, mHost.getContext(), false);
// 触发Fragment的onAttach回调方法
f.performAttach();
if (f.mParentFragment == null) {
// 触发FragmentActivity的onAttachFragment回调方法
mHost.onAttachFragment(f);
} else {
f.mParentFragment.onAttachFragment(f);
}
dispatchOnFragmentAttached(f, mHost.getContext(), false);
// mIsCreated默认为false
if (!f.mIsCreated) {
dispatchOnFragmentPreCreated(f, f.mSavedFragmentState, false);
// 设置mState为CREATED,触发Fragment的onCreate回调方法,并设置mIsCreated为true
f.performCreate(f.mSavedFragmentState);
dispatchOnFragmentCreated(f, f.mSavedFragmentState, false);
} else {
f.restoreChildFragmentState(f.mSavedFragmentState);
f.mState = Fragment.CREATED;
}
}
// fall through
// 没有break,继续往下执行
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);
// 判断该fragment不是通过布局xml中定义
if (!f.mFromLayout) {
ViewGroup container = null;
if (f.mContainerId != 0) {
// 若添加该fragment时有指定布局容器ID,则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(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;
// 触发Fragment的onCreateView回调方法,生成view并保存在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);
}
// 触发Fragment的onViewCreated回调方法
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;
}
}
// mState设置为ACTIVITY_CREATED,触发Fragment的onActivityCreated回调方法
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);
// mState设置为STARTED,触发Fragment的onStart回调方法
f.performStart();
dispatchOnFragmentStarted(f, false);
}
// fall through
case Fragment.STARTED:
if (newState > Fragment.STARTED) {
if (DEBUG) Log.v(TAG, "moveto RESUMED: " + f);
// mState设置为RESUMED,触发Fragment的onResume回调方法
f.performResume();
dispatchOnFragmentResumed(f, false);
f.mSavedFragmentState = null;
f.mSavedViewState = null;
}
}
} else if (f.mState > newState) {
// ···
}
// ···
}
可以看出,该方法第二部分中会判断目标状态和fragment当前状态的高低,若目标状态较高,则fragment向上生长,逐步更新状态值并执行对应阶段的处理逻辑。
[FragmentManagerImpl.java]
// 参数f为将要处理的Fragment,newState为将要设置的目标状态
void moveToState(Fragment f, int newState, int transit, int transitionStyle,
boolean keepActive) {
// ···
if (f.mState <= newState) {
// ···
} else if (f.mState > newState) {
// 若fragment当前生命周期状态高于目标状态,那么会进行从resumed(假设)到destroy(假设)的衰减过程
switch (f.mState) {
case Fragment.RESUMED:
if (newState < Fragment.RESUMED) {
if (DEBUG) Log.v(TAG, "movefrom RESUMED: " + f);
// mState置为STARTED,触发Fragment的onPause回调
f.performPause();
dispatchOnFragmentPaused(f, false);
}
// fall through
case Fragment.STARTED:
if (newState < Fragment.STARTED) {
if (DEBUG) Log.v(TAG, "movefrom STARTED: " + f);
// mState置为ACTIVITY_CREATED,触发Fragment的onStop回调
f.performStop();
dispatchOnFragmentStopped(f, false);
}
// fall through
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);
}
}
// mState置为CREATED,触发Fragment的onDestroyView回调
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);
}
// 从布局容器中移除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 || 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);
}
// mState置为INITIALIZING,触发Fragment的onDestroy回调
f.performDestroy();
dispatchOnFragmentDestroyed(f, false);
} else {
f.mState = Fragment.INITIALIZING;
}
// 触发Fragment的onDetach回调
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);
// 将目标状态赋值给fragment的mState
f.mState = newState;
}
}
当目标状态低于fragment当前生命周期状态时,则会进行和生长过程相反的过程。
总结
FragmentActivity在各个生命周期回调方法中会更新FragmentManagerImpl的生命周期状态,而FragmentManagerImpl接着就会遍历更新其所管理的Fragment集合,依次取出Fragment更新它的生命周期状态。更新Fragment的过程中会逐步调整它的状态至相邻生命周期状态,并进行对应阶段的处理和执行对应生命周期回调方法,最终更新到和FragmentManagerImpl的状态一致。