AndroidX Fragment探究-生命週期

概述

Fragment的生命週期依託FragmentActivity管理調度,在FragmentActivity的各個生命週期方法回調中,會將對應生命狀態派發給依附於FragmentActivity的所有Fragment。

fragment_lifecycle

圖1.Fragment 生命週期

源碼探究

文中源碼基於’androidx.fragment:fragment:1.1.0’

Fragment的生命週期派發

activity_fragment_lifecycle

圖2.Activity 生命週期對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當前生命週期狀態時,則會進行和生長過程相反的過程。

fragment-state

總結

FragmentActivity在各個生命週期回調方法中會更新FragmentManagerImpl的生命週期狀態,而FragmentManagerImpl接着就會遍歷更新其所管理的Fragment集合,依次取出Fragment更新它的生命週期狀態。更新Fragment的過程中會逐步調整它的狀態至相鄰生命週期狀態,並進行對應階段的處理和執行對應生命週期回調方法,最終更新到和FragmentManagerImpl的狀態一致。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章