Fragment(二) 一、生命週期調用流程 二、Fragment 三、提交任務

Android知識總結
注意:分析的是 androidx

一、生命週期調用流程

運用Fragment時,Activity 要繼承 FragmentActivity,我們先看FragmentActivity#onCreate

    final FragmentController mFragments = FragmentController.createController(new HostCallbacks()); 
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        mFragments.attachHost(null /*parent*/);

        if (savedInstanceState != null) {
            Parcelable p = savedInstanceState.getParcelable(FRAGMENTS_TAG);
            //把之前保存的數據取回來
            mFragments.restoreSaveState(p);

            // Check if there are any pending onActivityResult calls to descendent Fragments.
            if (savedInstanceState.containsKey(NEXT_CANDIDATE_REQUEST_INDEX_TAG)) {
                mNextCandidateRequestIndex =
                        savedInstanceState.getInt(NEXT_CANDIDATE_REQUEST_INDEX_TAG);
                int[] requestCodes = savedInstanceState.getIntArray(ALLOCATED_REQUEST_INDICIES_TAG);
                String[] fragmentWhos = savedInstanceState.getStringArray(REQUEST_FRAGMENT_WHO_TAG);
                if (requestCodes == null || fragmentWhos == null ||
                        requestCodes.length != fragmentWhos.length) {
                    Log.w(TAG, "Invalid requestCode mapping in savedInstanceState.");
                } else {
                    mPendingFragmentActivityResults = new SparseArrayCompat<>(requestCodes.length);
                    for (int i = 0; i < requestCodes.length; i++) {
                        mPendingFragmentActivityResults.put(requestCodes[i], fragmentWhos[i]);
                    }
                }
            }
        }

        if (mPendingFragmentActivityResults == null) {
            mPendingFragmentActivityResults = new SparseArrayCompat<>();
            mNextCandidateRequestIndex = 0;
        }

        super.onCreate(savedInstanceState);
        //更改狀態
        mFragmentLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);
        //分發 熾熱create 事件
        mFragments.dispatchCreate();
    }

接下來看FragmentController#dispatchCreate

    public void dispatchCreate() {
        mHost.mFragmentManager.dispatchCreate();
    }

調用FragmentManagerImpl#dispatchCreate

    public void dispatchCreate() {
        //保存狀態的標誌位 = false
        mStateSaved = false;
        mStopped = false;
        dispatchStateChange(Fragment.CREATED);
    }

    private void dispatchStateChange(int nextState) {
        try {
            mExecutingActions = true;
            //重新執行fragment生命週期
            moveToState(nextState, false);
        } finally {
            mExecutingActions = false;
        }
        execPendingActions();
    }

    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
        final int numAdded = mAdded.size();
        for (int i = 0; i < numAdded; i++) {
            Fragment f = mAdded.get(i);
            //最終會執行 moveToState 重新執行fragment生命週期
            moveFragmentToExpectedState(f);
        }

        // Now iterate through all active fragments. These will include those that are removed
        // and detached.
        for (Fragment f : mActive.values()) {
            if (f != null && (f.mRemoving || f.mDetached) && !f.mIsNewlyAdded) {
                //最終會執行 moveToState 重新執行fragment生命週期
                moveFragmentToExpectedState(f);
            }
        }

        startPendingDeferredFragments();

        if (mNeedMenuInvalidate && mHost != null && mCurState == Fragment.RESUMED) {
            mHost.onSupportInvalidateOptionsMenu();
            mNeedMenuInvalidate = false;
        }
    }

接下來我們看FragmentActivity#onCreateView 方法創建view,的過程

    public View onCreateView(@Nullable View parent, @NonNull String name, @NonNull Context context,
            @NonNull AttributeSet attrs) {
        // 創建 Fragment 的視圖
        final View v = dispatchFragmentsOnCreateView(parent, name, context, attrs);
        if (v == null) {
            //執行父類的 onCreateView
            return super.onCreateView(parent, name, context, attrs);
        }
        return v;
    }

    @Nullable
    final View dispatchFragmentsOnCreateView(@Nullable View parent, @NonNull String name,
            @NonNull Context context, @NonNull AttributeSet attrs) {
        //執行 FragmentController  的 onCreateView
        return mFragments.onCreateView(parent, name, context, attrs);
    }

FragmentController時 Fragment 的控制器, FragmentActivity上的所有生命週期相關API都會調用FragmentController對應的dispatchXXX()

    //FragmentManagerImpl 是 FragmentManager 的實現類
    final FragmentManagerImpl mFragmentManager = new FragmentManagerImpl();

    public View onCreateView(@Nullable View parent, @NonNull String name, @NonNull Context context,
            @NonNull AttributeSet attrs) {
        return mHost.mFragmentManager.onCreateView(parent, name, context, attrs);
    }

執行FragmentManagerImpl#onCreateView方法

    public View onCreateView(@Nullable View parent, @NonNull String name, @NonNull Context context,
                             @NonNull AttributeSet attrs) {
        if (!"fragment".equals(name)) {
            return null;
        }

        String fname = attrs.getAttributeValue(null, "class");
        TypedArray a =  context.obtainStyledAttributes(attrs, FragmentManagerImpl.FragmentTag.Fragment);
        if (fname == null) {
            fname = a.getString(FragmentManagerImpl.FragmentTag.Fragment_name);
        }
        int id = a.getResourceId(FragmentManagerImpl.FragmentTag.Fragment_id, View.NO_ID);
        String tag = a.getString(FragmentManagerImpl.FragmentTag.Fragment_tag);
        a.recycle();

        if (fname == null || !FragmentFactory.isFragmentClass(context.getClassLoader(), fname)) {
            return null;
        }

        int containerId = parent != null ? parent.getId() : 0;
        if (containerId == View.NO_ID && id == View.NO_ID && tag == null) {
            throw new IllegalArgumentException(attrs.getPositionDescription()
                    + ": Must specify unique android:id, android:tag, or have a parent with an id for " + fname);
        }

        //如果 id != -1,通過 id 創建 fragment
        Fragment fragment = id != View.NO_ID ? findFragmentById(id) : null;
        if (fragment == null && tag != null) {
            //通過 tag 創建 fragment
            fragment = findFragmentByTag(tag);
        }
        if (fragment == null && containerId != View.NO_ID) {
            //通過 id 創建 fragment
            fragment = findFragmentById(containerId);
        }

        if (FragmentManagerImpl.DEBUG) Log.v(TAG, "onCreateView: id=0x"
                + Integer.toHexString(id) + " fname=" + fname
                + " existing=" + fragment);
        if (fragment == null) {
            //通過反射創建 Fragment
            fragment = getFragmentFactory().instantiate(context.getClassLoader(), fname);
            fragment.mFromLayout = true;
            fragment.mFragmentId = id != 0 ? id : containerId;
            fragment.mContainerId = containerId;
            fragment.mTag = tag;
            fragment.mInLayout = true;
            fragment.mFragmentManager = this;
            fragment.mHost = mHost;
            fragment.onInflate(mHost.getContext(), attrs, fragment.mSavedFragmentState);
            addFragment(fragment, true);

        } else if (fragment.mInLayout) {
            // A fragment already exists and it is not one we restored from
            // previous state.
            throw new IllegalArgumentException(attrs.getPositionDescription()
                    + ": Duplicate id 0x" + Integer.toHexString(id)
                    + ", tag " + tag + ", or parent id 0x" + Integer.toHexString(containerId)
                    + " with another fragment for " + fname);
        } else {
            // This fragment was retained from a previous instance; get it
            // going now.
            fragment.mInLayout = true;
            fragment.mHost = mHost;
            // Give the Fragment the attributes to initialize itself.
            fragment.onInflate(mHost.getContext(), attrs, fragment.mSavedFragmentState);
        }

        //當前的狀態 mCurState < CREATED
        if (mCurState < Fragment.CREATED && fragment.mFromLayout) {
            //更新狀態,執行 fragment 的生命週期
            moveToState(fragment, Fragment.CREATED, 0, 0, false);
        } else {
            moveToState(fragment);
        }

        if (fragment.mView == null) {
            throw new IllegalStateException("Fragment " + fname
                    + " did not create a view.");
        }
        if (id != 0) {
            //設置 id
            fragment.mView.setId(id);
        }
        if (fragment.mView.getTag() == null) {
            //設置 tag
            fragment.mView.setTag(tag);
        }
        return fragment.mView;
    }

執行FragmentManagerImpl#moveToState

    void moveToState(Fragment f, int newState, int transit, int transitionStyle,
                     boolean keepActive) {
        // 還沒有添加的 Fragment 處於 onCreate() 狀態
        if ((!f.mAdded || f.mDetached) && newState > Fragment.CREATED) {
            newState = Fragment.CREATED;
        }
        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.
        //推遲啓動的設置爲 created
        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.
        if (f.mMaxState == Lifecycle.State.CREATED) {
            newState = Math.min(newState, Fragment.CREATED);
        } else {
            newState = Math.min(newState, f.mMaxState.ordinal());
        }
        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) {
                return;
            }
            if (f.getAnimatingAway() != null || f.getAnimator() != null) {
                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) {
                            f.mSavedFragmentState.setClassLoader(mHost.getContext()
                                    .getClassLoader());
                            f.mSavedViewState = f.mSavedFragmentState.getSparseParcelableArray(
                                    FragmentManagerImpl.VIEW_STATE_TAG);
                            Fragment target = getFragment(f.mSavedFragmentState,
                                    FragmentManagerImpl.TARGET_STATE_TAG);
                            f.mTargetWho = target != null ? target.mWho : null;
                            if (f.mTargetWho != null) {
                                f.mTargetRequestCode = f.mSavedFragmentState.getInt(
                                        FragmentManagerImpl.TARGET_REQUEST_CODE_STATE_TAG, 0);
                            }
                            if (f.mSavedUserVisibleHint != null) {
                                f.mUserVisibleHint = f.mSavedUserVisibleHint;
                                f.mSavedUserVisibleHint = null;
                            } else {
                                f.mUserVisibleHint = f.mSavedFragmentState.getBoolean(
                                        FragmentManagerImpl.USER_VISIBLE_HINT_TAG, true);
                            }
                            if (!f.mUserVisibleHint) {
                                f.mDeferStart = true;
                                if (newState > Fragment.ACTIVITY_CREATED) {
                                    newState = Fragment.ACTIVITY_CREATED;
                                }
                            }
                        }

                        f.mHost = mHost;
                        f.mParentFragment = mParent;
                        f.mFragmentManager = mParent != null
                                ? mParent.mChildFragmentManager : mHost.mFragmentManager;

                        // 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 (mActive.get(f.mTarget.mWho) != f.mTarget) {
                                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, 0, 0, true);
                            }
                            f.mTargetWho = f.mTarget.mWho;
                            f.mTarget = null;
                        }
                        if (f.mTargetWho != null) {
                            Fragment target = mActive.get(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, 0, 0, true);
                            }
                        }

                        dispatchOnFragmentPreAttached(f, mHost.getContext(), false);
                        //調用 Fragment 生命週期 onAttach 方法
                        f.performAttach();
                        if (f.mParentFragment == null) {
                            mHost.onAttachFragment(f);
                        } else {
                            f.mParentFragment.onAttachFragment(f);
                        }
                        dispatchOnFragmentAttached(f, mHost.getContext(), false);

                        if (!f.mIsCreated) {
                            dispatchOnFragmentPreCreated(f, f.mSavedFragmentState, false);
                            //調用 Fragment生命週期 onCreate 方法
                            f.performCreate(f.mSavedFragmentState);
                            dispatchOnFragmentCreated(f, f.mSavedFragmentState, false);
                        } else {
                            f.restoreChildFragmentState(f.mSavedFragmentState);
                            f.mState = Fragment.CREATED;
                        }
                    }
                    // fall through
                case Fragment.CREATED:
                    if (newState > Fragment.INITIALIZING) {
                        ensureInflatedFragmentView(f);
                    }

                    if (newState > Fragment.CREATED) {
                        if (DEBUG) Log.v(TAG, "moveto ACTIVITY_CREATED: " + f);
                        if (!f.mFromLayout) {
                            ViewGroup container = null;
                            if (f.mContainerId != 0) {
                                if (f.mContainerId == View.NO_ID) {
                                    throwException(new IllegalArgumentException(
                                            "Cannot create fragment "
                                                    + f
                                                    + " for a container view with no 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 方法
                            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 的佈局添加到父佈局中
                                    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;
                            }
                        }
                        //調用 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);
                        //調用 Fragment 生命週期 onStart 方法
                        f.performStart();
                        dispatchOnFragmentStarted(f, false);
                    }
                    // fall through
                case Fragment.STARTED:
                    if (newState > Fragment.STARTED) {
                        if (DEBUG) Log.v(TAG, "moveto RESUMED: " + f);
                        //調用 Fragment 生命週期 onResume 方法
                        f.performResume();
                        dispatchOnFragmentResumed(f, false);
                        f.mSavedFragmentState = null;
                        f.mSavedViewState = null;
                    }
            }
        } else if (f.mState > newState) {
            switch (f.mState) {
                case Fragment.RESUMED:
                    if (newState < Fragment.RESUMED) {
                        if (DEBUG) Log.v(TAG, "movefrom RESUMED: " + f);
                        //調用 Fragment 生命週期 onPause 方法
                        f.performPause();
                        dispatchOnFragmentPaused(f, false);
                    }
                    // fall through
                case Fragment.STARTED:
                    if (newState < Fragment.STARTED) {
                        if (DEBUG) Log.v(TAG, "movefrom STARTED: " + f);
                        //調用 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);
                            }
                        }
                        //調用 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();
                            FragmentManagerImpl.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);
                                }
                                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) {
                            if (f.getAnimatingAway() != null) {
                                View v = f.getAnimatingAway();
                                f.setAnimatingAway(null);
                                v.clearAnimation();
                            } else if (f.getAnimator() != null) {
                                Animator animator = f.getAnimator();
                                f.setAnimator(null);
                                animator.cancel();
                            }
                        }
                        if (f.getAnimatingAway() != null || f.getAnimator() != null) {
                            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);
                                }
                                //調用 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);
            f.mState = newState;
        }
    }

我們看線Fragment#performResume,其他生命週期類同

    void performResume() {
        mChildFragmentManager.noteStateNotSaved();
        mChildFragmentManager.execPendingActions();
        mState = RESUMED;
        mCalled = false;
        onResume();
        if (!mCalled) {
            throw new SuperNotCalledException("Fragment " + this
                    + " did not call through to super.onResume()");
        }
        mLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_RESUME);
        if (mView != null) {
            mViewLifecycleOwner.handleLifecycleEvent(Lifecycle.Event.ON_RESUME);
        }
        mChildFragmentManager.dispatchResume();
        mChildFragmentManager.execPendingActions();
    }

執行FragmentManagerImpl#dispatchResume 分發事件

    public void dispatchResume() {
        mStateSaved = false;
        mStopped = false;
        dispatchStateChange(Fragment.RESUMED);
    }

    private void dispatchStateChange(int nextState) {
        try {
            mExecutingActions = true;
            //改變狀態
            moveToState(nextState, false);
        } finally {
            mExecutingActions = false;
        }
        execPendingActions();
    }

二、Fragment

public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener, LifecycleOwner,
        ViewModelStoreOwner, SavedStateRegistryOwner {
    static final Object USE_DEFAULT_TRANSITION = new Object();
    static final int INITIALIZING = 0;     // Fragment尚未初始化或者已經被銷燬
    static final int CREATED = 1;          // Fragment已被創建.
    static final int ACTIVITY_CREATED = 2; // Fragment所在Activity已經創建成功
    static final int STARTED = 3;          // Fragment已經可見,但是還不可以接收點擊事件
    static final int RESUMED = 4;          //Fragment已經可見並且可以接收點擊事件
    //當前 Fragment 的狀態值
    int mState = INITIALIZING;

    // When instantiated from saved state, this is the saved state.
    Bundle mSavedFragmentState;
    SparseArray<Parcelable> mSavedViewState;
    @Nullable Boolean mSavedUserVisibleHint;
    @NonNull
    String mWho = UUID.randomUUID().toString();
    Bundle mArguments;
    Fragment mTarget;
    String mTargetWho = null;
    int mTargetRequestCode;
    private Boolean mIsPrimaryNavigationFragment = null;
    //是否被添加
    boolean mAdded;
    //是否被移除
    boolean mRemoving;
    boolean mFromLayout;
    boolean mInLayout;
    boolean mRestored;
    boolean mPerformedCreateView;
    int mBackStackNesting;
    FragmentManagerImpl mFragmentManager;
   //Fragmemt 綁定的對象,一半就是 Activity 和 Fragmen
    FragmentHostCallback mHost;
    // 管理子 Fragment
    @NonNull
    FragmentManagerImpl mChildFragmentManager = new FragmentManagerImpl();
    //如果這個 Fragment 綁定的是另一個 Fragment,就需要設置這個值
    Fragment mParentFragment;
    // 容器 Fragment 的ID
    int mFragmentId;
    // 容器 View 的ID
    int mContainerId;
    String mTag;
    //是否被隱藏
    boolean mHidden;
    //是否已經分離
    boolean mDetached;
    boolean mRetainInstance;
    boolean mRetainInstanceChangedWhileDetached;
    boolean mHasMenu;
    boolean mMenuVisible = true;
    private boolean mCalled;

    // 父佈局
    ViewGroup mContainer;
    //當前 Fragment 的佈局
    //在 onCreateView() 中返回一個 佈局,
    //然後在 FragmentManager 中拿到這個佈局,
    //添加到要綁定容器(Activity/Fragment)的 ViewGroup 中,然後設置相應的狀態值
    View mView;
    // 真正保存狀態的內部佈局
    View mInnerView;
    boolean mDeferStart;
    boolean mUserVisibleHint = true;
    AnimationInfo mAnimationInfo;
    Runnable mPostponedDurationRunnable = new Runnable() {
        @Override
        public void run() {
            startPostponedEnterTransition();
        }
    };
    boolean mIsNewlyAdded;
    boolean mHiddenChanged;
    float mPostponedAlpha;
    LayoutInflater mLayoutInflater;
    boolean mIsCreated;
    Lifecycle.State mMaxState = Lifecycle.State.RESUMED;
    LifecycleRegistry mLifecycleRegistry;
    @Nullable FragmentViewLifecycleOwner mViewLifecycleOwner;
    MutableLiveData<LifecycleOwner> mViewLifecycleOwnerLiveData = new MutableLiveData<>();

    SavedStateRegistryController mSavedStateRegistryController;

    @LayoutRes
    private int mContentLayoutId;
}

三、提交任務

注意:執行 commitxxx() 方法之後,才正式執行fragment的生命週期。
執行FragmentTransaction的實現類BackStackRecordcommit

    public int commit() {
        //異步任務
        return commitInternal(false);
    }

    @Override
    public int commitAllowingStateLoss() {
        //異步任務
        return commitInternal(true);
    }

    @Override
    public void commitNow() {
        disallowAddToBackStack();
        //同步任務
        mManager.execSingleAction(this, false);
    }

    @Override
    public void commitNowAllowingStateLoss() {
        disallowAddToBackStack();
        // 同步任務
        mManager.execSingleAction(this, true);
    }

    //allowStateLoss :是否允許保存狀態
    int commitInternal(boolean allowStateLoss) {
        if (mCommitted) throw new IllegalStateException("commit already called");
        if (FragmentManagerImpl.DEBUG) {
            Log.v(TAG, "Commit: " + this);
            LogWriter logw = new LogWriter(TAG);
            PrintWriter pw = new PrintWriter(logw);
            dump("  ", pw);
            pw.close();
        }
        mCommitted = true;
        if (mAddToBackStack) {
            //更新 index 信息
            mIndex = mManager.allocBackStackIndex(this);
        } else {
            mIndex = -1;
        }
        //異步任務入隊
        mManager.enqueueAction(this, allowStateLoss);
        return mIndex;
    }

執行FragmentManagerImpl#enqueueAction異步任務

    public void enqueueAction(OpGenerator action, boolean allowStateLoss) {
        //校驗狀態是否保存
        if (!allowStateLoss) {
            checkStateLoss();
        }
        synchronized (this) {
            if (mDestroyed || mHost == null) {
                if (allowStateLoss) {
                    //如果  allowStateLoss = true,直接退出。表示不會提交任務,丟棄保存的 state
                    return;
                }
                throw new IllegalStateException("Activity has been destroyed");
            }
            if (mPendingActions == null) {
                mPendingActions = new ArrayList<>();
            }
            mPendingActions.add(action);
             //發送任務
            scheduleCommit();
        }
    }

校驗狀態

    private void checkStateLoss() {
        //在 onSaveInstanceState 保存狀態後,isStateSaved == true
        //當狀態保存之後,在執行 commit 就會報此錯誤
        if (isStateSaved()) {
            throw new IllegalStateException(
                    "Can not perform this action after onSaveInstanceState");
        }
    }

    public boolean isStateSaved() {
        return mStateSaved || mStopped;
    }
  • mStateSaved狀態置爲true,是在Activity 執行 onSaveInstanceState 保存狀態之後。
    protected void onSaveInstanceState(@NonNull Bundle outState) {
        super.onSaveInstanceState(outState);
        markFragmentsCreated();
        mFragmentLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_STOP);
        //保存狀態
        Parcelable p = mFragments.saveAllState();
        //序列化信息
        if (p != null) {
            outState.putParcelable(FRAGMENTS_TAG, p);
        }
        if (mPendingFragmentActivityResults.size() > 0) {
            outState.putInt(NEXT_CANDIDATE_REQUEST_INDEX_TAG, mNextCandidateRequestIndex);

            int[] requestCodes = new int[mPendingFragmentActivityResults.size()];
            String[] fragmentWhos = new String[mPendingFragmentActivityResults.size()];
            for (int i = 0; i < mPendingFragmentActivityResults.size(); i++) {
                requestCodes[i] = mPendingFragmentActivityResults.keyAt(i);
                fragmentWhos[i] = mPendingFragmentActivityResults.valueAt(i);
            }
            outState.putIntArray(ALLOCATED_REQUEST_INDICIES_TAG, requestCodes);
            outState.putStringArray(REQUEST_FRAGMENT_WHO_TAG, fragmentWhos);
        }
    }

執行FragmentController#saveAllState

    public Parcelable saveAllState() {
        return mHost.mFragmentManager.saveAllState();
    }

執行FragmentManagerImpl#saveAllState

    Parcelable saveAllState() {.
        forcePostponedTransactions();
        endAnimatingAwayFragments();
        execPendingActions();
        //標誌位至 true
        mStateSaved = true;

        if (mActive.isEmpty()) {
            return null;
        }
    }
  • 提交任務
    void scheduleCommit() {
        synchronized (this) {
            boolean postponeReady =
                    mPostponedTransactions != null && !mPostponedTransactions.isEmpty();
            boolean pendingReady = mPendingActions != null && mPendingActions.size() == 1;
            if (postponeReady || pendingReady) {
                //通過 handler 發送異步消息
                mHost.getHandler().removeCallbacks(mExecCommit);
                mHost.getHandler().post(mExecCommit);
                updateOnBackPressedCallbackEnabled();
            }
        }
    }

接下來在 FragmentManagerImpl 類中看異步任務

    Runnable mExecCommit = new Runnable() {
        @Override
        public void run() {
            execPendingActions();
        }
    };

在主線程中更新 UI 嘛

    public boolean execPendingActions() {
        ensureExecReady(true);

        boolean didSomething = false;
        while (generateOpsForPendingActions(mTmpRecords, mTmpIsPop)) {
            mExecutingActions = true;
            try {
                removeRedundantOperationsAndExecute(mTmpRecords, mTmpIsPop);
            } finally {
                cleanupExec();
            }
            didSomething = true;
        }

        updateOnBackPressedCallbackEnabled();
        doPendingDeferredStart();
        burpActive();

        return didSomething;
    }
    private void removeRedundantOperationsAndExecute(ArrayList<BackStackRecord> records,
                                                     ArrayList<Boolean> isRecordPop) {
        if (records == null || records.isEmpty()) {
            return;
        }

        if (isRecordPop == null || 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:
        executePostponedTransaction(records, isRecordPop);

        final int numRecords = records.size();
        int startIndex = 0;
        for (int recordNum = 0; recordNum < numRecords; recordNum++) {
            final boolean canReorder = records.get(recordNum).mReorderingAllowed;
            if (!canReorder) {
                // execute all previous transactions
                if (startIndex != recordNum) {
                    //這裏將 Ops 過濾一遍
                    executeOpsTogether(records, isRecordPop, startIndex, recordNum);
                }
                // execute all pop operations that don't allow reordering together or
                // one add operation
                int reorderingEnd = recordNum + 1;
                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) {
            executeOpsTogether(records, isRecordPop, startIndex, numRecords);
        }
    }
    private void executeOpsTogether(ArrayList<BackStackRecord> records,
                                    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(mAdded);
        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);
        }
        //真正處理的入口
        executeOps(records, isRecordPop, startIndex, endIndex);

        int postponeIndex = endIndex;
        if (allowReordering) {
            ArraySet<Fragment> addedFragments = new ArraySet<>();
            addAddedFragments(addedFragments);
            postponeIndex = postponePostponableTransactions(records, isRecordPop,
                    startIndex, endIndex, addedFragments);
            //設置將要被移除的 Fragment 爲不可見的最終實現
            makeRemovedFragmentsInvisible(addedFragments);
        }

        if (postponeIndex != startIndex && allowReordering) {
            // need to run something now
            FragmentTransition.startTransitions(this, records, isRecordPop, startIndex,
                    postponeIndex, true);
            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) {
                freeBackStackIndex(record.mIndex);
                record.mIndex = -1;
            }
            record.runOnCommitRunnables();
        }
        if (addToBackStack) {
            reportBackStackChanged();
        }
    }

然後在BackStackRecord#expandOps看修改Ops 狀態,這一步還沒有真正處理狀態

    Fragment expandOps(ArrayList<Fragment> added, Fragment oldPrimaryNav) {
        for (int opNum = 0; opNum < mOps.size(); opNum++) {
            final Op op = mOps.get(opNum);
            switch (op.mCmd) {
                case OP_ADD:
                case OP_ATTACH:
                    added.add(op.mFragment);
                    break;
                case OP_REMOVE:
                case OP_DETACH: {
                    added.remove(op.mFragment);
                    if (op.mFragment == oldPrimaryNav) {
                        mOps.add(opNum, new Op(OP_UNSET_PRIMARY_NAV, op.mFragment));
                        opNum++;
                        oldPrimaryNav = null;
                    }
                }
                break;
                case OP_REPLACE: {
                    final Fragment f = op.mFragment;
                    final int containerId = f.mContainerId;
                    boolean alreadyAdded = false;
                    for (int i = added.size() - 1; i >= 0; i--) {
                        final Fragment old = added.get(i);
                        if (old.mContainerId == containerId) {
                            if (old == f) {
                                alreadyAdded = true;
                            } else {
                                // This is duplicated from above since we only make
                                // a single pass for expanding ops. Unset any outgoing primary nav.
                                if (old == oldPrimaryNav) {
                                    mOps.add(opNum, new Op(OP_UNSET_PRIMARY_NAV, old));
                                    opNum++;
                                    oldPrimaryNav = null;
                                }
                                //可以看到,替換也是通過刪除實現的
                                final Op removeOp = new Op(OP_REMOVE, old);
                                removeOp.mEnterAnim = op.mEnterAnim;
                                removeOp.mPopEnterAnim = op.mPopEnterAnim;
                                removeOp.mExitAnim = op.mExitAnim;
                                removeOp.mPopExitAnim = op.mPopExitAnim;
                                mOps.add(opNum, removeOp);
                                added.remove(old);
                                opNum++;
                            }
                        }
                    }
                    if (alreadyAdded) {
                        mOps.remove(opNum);
                        opNum--;
                    } else {
                        op.mCmd = OP_ADD;
                        added.add(f);
                    }
                }
                break;
                case OP_SET_PRIMARY_NAV: {
                    // It's ok if this is null, that means we will restore to no active
                    // primary navigation fragment on a pop.
                    mOps.add(opNum, new Op(OP_UNSET_PRIMARY_NAV, oldPrimaryNav));
                    opNum++;
                    // Will be set by the OP_SET_PRIMARY_NAV we inserted before when run
                    oldPrimaryNav = op.mFragment;
                }
                break;
            }
        }
        return oldPrimaryNav;
    }

將要被移除的 Fragment 爲不可見的最終實現

    private void makeRemovedFragmentsInvisible(ArraySet<Fragment> fragments) {
        final int numAdded = fragments.size();
        for (int i = 0; i < numAdded; i++) {
            final Fragment fragment = fragments.valueAt(i);
            if (!fragment.mAdded) {
                final View view = fragment.requireView();
                fragment.mPostponedAlpha = view.getAlpha();
                //設爲透明
                view.setAlpha(0f);
            }
        }
    }
  • FragmentTransaction中可看到內部類OpOp 就是添加了狀態和動畫信息的 Fragment, mOps 就是棧中所有的 Fragment。
    static final class Op {
        int mCmd;  //狀態
        Fragment mFragment;
        int mEnterAnim;
        int mExitAnim;
        int mPopEnterAnim;
        int mPopExitAnim;
        Lifecycle.State mOldMaxState;
        Lifecycle.State mCurrentMaxState;

        Op() {
        }

        Op(int cmd, Fragment fragment) {
            this.mCmd = cmd; 
            this.mFragment = fragment;
            this.mOldMaxState = Lifecycle.State.RESUMED;
            this.mCurrentMaxState = Lifecycle.State.RESUMED;
        }

        Op(int cmd, @NonNull Fragment fragment, Lifecycle.State state) {
            this.mCmd = cmd;  
            this.mFragment = fragment;
            this.mOldMaxState = fragment.mMaxState;
            this.mCurrentMaxState = state;
        }
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章