欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

AndroidX Fragment探究-生命周期

程序员文章站 2022-06-08 11:07:03
...

概述

Fragment的生命周期依托FragmentActivity管理调度,在FragmentActivity的各个生命周期方法回调中,会将对应生命状态派发给依附于FragmentActivity的所有Fragment。

AndroidX Fragment探究-生命周期

图1.Fragment 生命周期

源码探究

文中源码基于’androidx.fragment:fragment:1.1.0’

Fragment的生命周期派发

AndroidX Fragment探究-生命周期

图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当前生命周期状态时,则会进行和生长过程相反的过程。

AndroidX Fragment探究-生命周期

总结

FragmentActivity在各个生命周期回调方法中会更新FragmentManagerImpl的生命周期状态,而FragmentManagerImpl接着就会遍历更新其所管理的Fragment集合,依次取出Fragment更新它的生命周期状态。更新Fragment的过程中会逐步调整它的状态至相邻生命周期状态,并进行对应阶段的处理和执行对应生命周期回调方法,最终更新到和FragmentManagerImpl的状态一致。

相关标签: Android