文章目錄
概述
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的狀態一致。