美文网首页Android开发
Fragment(AndroidX版本)源码解析(一)

Fragment(AndroidX版本)源码解析(一)

作者: 取了个很好听的名字 | 来源:发表于2021-10-12 15:55 被阅读0次

    前言

    本文为个人学习Fragment源码时所总结形成的文章。本文主要梳理Fragment生命周期的调用流程

    Fragment的声明流程。

    如大家所知道的,Fragment被称为'碎片',我理解的碎片就是可以将fragment嵌入到相关的activity页面中,展示相关的布局,并能够监听activity的相关声明周期,并执行相关的逻辑。

    class MainActivity : AppCompatActivity() {
    
        companion object {
            private const val TAG = "MainActivity"
        }
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
            Log.e(TAG, "onCreate: ")
        }
    }
    
    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">
    
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Hello World!"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintLeft_toLeftOf="parent"
            app:layout_constraintRight_toRightOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    
        <fragment
            android:id="@+id/my"
            android:name="com.zxl.fragmentlifecycledemo.MyFragment"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    
    </androidx.constraintlayout.widget.ConstraintLayout>
    
    package com.zxl.fragmentlifecycledemo
    
    import android.content.Context
    import android.os.Bundle
    import android.util.Log
    import android.view.LayoutInflater
    import android.view.View
    import android.view.ViewGroup
    import androidx.fragment.app.Fragment
    
    class MyFragment : Fragment() {
    
        companion object {
            private const val TAG = "MyFragment"
        }
    
        override fun onAttach(context: Context) {
            super.onAttach(context)
            Log.e(TAG, "onAttach: ")
        }
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            Log.e(TAG, "onCreate: ")
        }
    
        override fun onActivityCreated(savedInstanceState: Bundle?) {
            super.onActivityCreated(savedInstanceState)
            Log.e(TAG, "onActivityCreated: ")
        }
    
        override fun onCreateView(
            inflater: LayoutInflater,
            container: ViewGroup?,
            savedInstanceState: Bundle?
        ): View? {
            val inflate = inflater.inflate(R.layout.fragment_main, container, false)
            Log.e(TAG, "onCreateView: ")
            return inflate
        }
    }
    

    运行后的结果如下:

    2021-10-11 15:39:31.871 14480-14480/com.zxl.fragmentlifecycledemo E/MyFragment: onAttach: 
    2021-10-11 15:39:31.871 14480-14480/com.zxl.fragmentlifecycledemo E/MyFragment: onCreate: 
    2021-10-11 15:39:31.874 14480-14480/com.zxl.fragmentlifecycledemo E/MyFragment: onCreateView: 
    2021-10-11 15:39:31.874 14480-14480/com.zxl.fragmentlifecycledemo E/MainActivity: onCreate: 
    2021-10-11 15:39:31.878 14480-14480/com.zxl.fragmentlifecycledemo E/MyFragment: onActivityCreated: 
    

    从代码运行的结果来说,在Activity执行完onCreate之前Fragment已经执行了onAttach,onCreate,onCreateViewdd这三个方法,在Activity的onCreate执行完之前,Fragment又调用了onActivityCreaged的方法。其实大家都知道,Activity会主动调用Fragemnt的相关周期(可以类比于ViewGroup的onMeasure,先测量完所有的子View最后才测量自己)。那我们就从Activity的onCreate方法作为入口看一下吧。
    AppCompatActivity的onCreate方法

     protected void onCreate(@Nullable Bundle savedInstanceState) {
            final AppCompatDelegate delegate = getDelegate();
            delegate.installViewFactory();
            delegate.onCreate(savedInstanceState);
            super.onCreate(savedInstanceState);
        }
    

    AppCompatActivity会调用FragmentActivity的onCreate方法

    protected void onCreate(@Nullable Bundle savedInstanceState) {
          ...
    
            super.onCreate(savedInstanceState);
            mFragmentLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);
           //这里调用了mFragments的dispatchCreate方法
            mFragments.dispatchCreate();
        ...
        
        
        }
    

    在FragmentActivity的onCreate方法中调用了dispatchCreate方法,首先注意调用方mFragments,这个mFragments是什么呢,其实就是FragmentController,我喜欢叫他'''大管家',他其实像一个静态代理一样,所有与Fragment的操作都通过mHost调用相关方法实现,而mHost调用mFragmentManager实现相关的操作

    public class FragmentController {
        private final FragmentHostCallback<?> mHost;
    
        /**
         * Returns a {@link FragmentController}.
         */
        @NonNull
        public static FragmentController createController(@NonNull FragmentHostCallback<?> callbacks) {
            return new FragmentController(checkNotNull(callbacks, "callbacks == null"));
        }
    
        private FragmentController(FragmentHostCallback<?> callbacks) {
            mHost = callbacks;
        }
    
        /**
         * Returns a {@link FragmentManager} for this controller.
         */
        @NonNull
        public FragmentManager getSupportFragmentManager() {
            return mHost.mFragmentManager;
        }
    
        /**
         * Returns a {@link LoaderManager}.
         *
         * @deprecated Loaders are managed separately from FragmentController and this now throws an
         * {@link UnsupportedOperationException}. Use {@link LoaderManager#getInstance} to obtain a
         * LoaderManager.
         * @see LoaderManager#getInstance
         */
        @Deprecated
        @SuppressLint("UnknownNullness")
        public LoaderManager getSupportLoaderManager() {
            throw new UnsupportedOperationException("Loaders are managed separately from "
                    + "FragmentController, use LoaderManager.getInstance() to obtain a LoaderManager.");
        }
    
        /**
         * Returns a fragment with the given identifier.
         */
        @Nullable
        public Fragment findFragmentByWho(@NonNull String who) {
            return mHost.mFragmentManager.findFragmentByWho(who);
        }
    .....
    }
    
    public abstract class FragmentHostCallback<E> extends FragmentContainer {
        @Nullable private final Activity mActivity;
        @NonNull private final Context mContext;
        @NonNull private final Handler mHandler;
        private final int mWindowAnimations;
       //FragmentHostCallBack持有FragmentManagerImpl 的实例
        final FragmentManagerImpl mFragmentManager = new FragmentManagerImpl();
    

    现在看一下mFragments的dispatchCreate方法

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

    该方法最终调用了FragmentHostCallBack持有的FragmentManagerImpl的dispatchCreate。FragmentManagerImpl的dispatchCreate方法如下

    public void dispatchCreate() {
            mStateSaved = false;
            mStopped = false;
           //调用dispatchStateChange
            dispatchStateChange(Fragment.CREATED);
        }
    

    这里需要注意的是Fragment.CREATED这个状态位,在Fragment总一共有五个状态(这里只说明AndroidX的版本)

    public class Fragment implements ComponentCallbacks, OnCreateContextMenuListener, LifecycleOwner,
            ViewModelStoreOwner, SavedStateRegistryOwner {
    
        static final Object USE_DEFAULT_TRANSITION = new Object();
    
        static final int INITIALIZING = 0;     // Not yet created.
        static final int CREATED = 1;          // Created.
        static final int ACTIVITY_CREATED = 2; // Fully created, not started.
        static final int STARTED = 3;          // Created and started, not resumed.
        static final int RESUMED = 4;          // Created started and resumed.
    
    

    不知道这里大家会不会奇怪为什么没有paused,Stoped之类的状态符,这是因为INITIALIZING ->RESUMED 这种算升序的话,RESUMED ->INITIALIZING 则可以理解为降序。没有必须再设置Paused之类。那么dispatchStateChange又干了什么呢?

        private void dispatchStateChange(int nextState) {
            try {
                mExecutingActions = true;
                //调用了moveToState方法
                moveToState(nextState, false);
            } finally {
                mExecutingActions = false;
            }
            execPendingActions();
        }
    

    这个方法就整个Fragment操作的一个核心方法,里面处理了各种fragment的声明周期的回调。

     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
           //将mAdded集合的fragment回调相关的声明周期
            final int numAdded = mAdded.size();
            for (int i = 0; i < numAdded; i++) {
                Fragment f = mAdded.get(i);
                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) {
                    moveFragmentToExpectedState(f);
                }
            }
    
            startPendingDeferredFragments();
    
            if (mNeedMenuInvalidate && mHost != null && mCurState == Fragment.RESUMED) {
                mHost.onSupportInvalidateOptionsMenu();
                mNeedMenuInvalidate = false;
            }
        }
    

    在该方法中循环遍历mAdded的Fragments,并moveFragmentToExpectedState,通过该方法回调各个Fragment的声明周期方法。

    void moveFragmentToExpectedState(Fragment f) {
            if (f == null) {
                return;
            }
            if (!mActive.containsKey(f.mWho)) {
                if (DEBUG) {
                    Log.v(TAG, "Ignoring moving " + f + " to state " + mCurState
                            + "since it is not added to " + this);
                }
                return;
            }
            int nextState = mCurState;
            if (f.mRemoving) {
                if (f.isInBackStack()) {
                    nextState = Math.min(nextState, Fragment.CREATED);
                } else {
                    nextState = Math.min(nextState, Fragment.INITIALIZING);
                }
            }
           //调用moveToState
            moveToState(f, nextState, f.getNextTransition(), f.getNextTransitionStyle(), false);
    
            ....
        }
    

    现在看一下moveToState这个方法

     void moveToState(Fragment f, int newState, int transit, int transitionStyle,
                         boolean keepActive) {
            .....
           //当前Frgamnet状态小于等于指定的状态状态,执行下面的方法
            if (f.mState <= newState) {
                   ....
            } else if (f.mState > newState) {
          //当前Frgamnet状态大于指定的状态状态,执行下面的方法
                   ......
                
            }
    
          ....
    

    现在看一下Fragment的mState小于等于newState的情况

       switch (f.mState) {
                    //当前Fragment状态为初始化状态
                    case Fragment.INITIALIZING:
                        if (newState > Fragment.INITIALIZING) {
                        .....
                            
                            f.mHost = mHost;
                            f.mParentFragment = mParent;
                            f.mFragmentManager = mParent != null
                                    ? mParent.mChildFragmentManager : mHost.mFragmentManager;
    
                            //调用Fragment的f.performAttach方法,该方法最终调用到Fragment的onAttach方法
                            f.performAttach();
                            if (f.mParentFragment == null) {
                                mHost.onAttachFragment(f);
                            } else {
                                f.mParentFragment.onAttachFragment(f);
                            }
                            dispatchOnFragmentAttached(f, mHost.getContext(), false);
                            //无论f.mIsCreate取值为何,都会将Fragment的状态置为 Fragment.CREATED
                            if (!f.mIsCreated) {
                                dispatchOnFragmentPreCreated(f, f.mSavedFragmentState, false);
                                //调用fragment的performCreate,最终会调用到Fragment的onCreate方法,该放回会将mState置为Fragment.CREATED
                                f.performCreate(f.mSavedFragmentState);
                                dispatchOnFragmentCreated(f, f.mSavedFragmentState, false);
                            } else {
                                f.restoreChildFragmentState(f.mSavedFragmentState);
                                f.mState = Fragment.CREATED;
                            }
                        }
                        // fall through
                    //这里没有break,所以会走到下面一个case
                    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) {
                            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;
                                //调用performCreateView,最终会调用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) {
                                        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,然后调用Fragemnt的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);
                            //该方法最终会调用Frament的onStart方法,并将mState置为STARTED
                            f.performStart();
                            dispatchOnFragmentStarted(f, false);
                        }
                        // fall through
                    case Fragment.STARTED:
                        if (newState > Fragment.STARTED) {
                            if (DEBUG) Log.v(TAG, "moveto RESUMED: " + f);
                            //最终调用Fragment的onReumse方法,将mState置为RESUMED
                            f.performResume();
                            dispatchOnFragmentResumed(f, false);
                            f.mSavedFragmentState = null;
                            f.mSavedViewState = null;
                        }
                }
    

    需要说明的有如下几点:
    1.每次case都没有break,也就是说所有的case语句都会执行到
    2.每个case都能调用Fragment的相关声明周期方法
    3.每个case中都会对当前的Fragment的mState与需要设置的state(nextState)进行比对,如果当前的nextState等于Fragment的mState则不再进入相关case的if语句(但仍会进入先关的case语句)

    这也就说明了Activity每执行一个生命周期都将让该Activity的相关mAdded的fragment回调对应的生命周期。其对应关系如下:

    201810010746476.png 。

    如果Activity执行onPause的话,会进入到FragmentActivity的dispatchPause

       protected void onPause() {
            super.onPause();
            mResumed = false;
            //执行FragmentHostCallBack的dispatchPause方法
            mFragments.dispatchPause();
            mFragmentLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_PAUSE);
        }
    

    FragmentHostCallBack.dispatchPause

    public void dispatchPause() {
             //调用FragmentManagerImpl的dispatchPause方法
            mHost.mFragmentManager.dispatchPause();
        }
    

    FragmentManagerImpl.dispatchPause

       public void dispatchPause() {
            dispatchStateChange(Fragment.STARTED);
        }
    

    最终仍然会调用到moveToState这一方法,如果此时Fragment为RESUMED状态的话,则会走moveToStated的else代码。else代码与if的代码逻辑上类似,但是每个case语句的if代码块都会让当前Fragment递减直到INITIALIZING。在递减的过程中都会调用Fragment的相关生命周期方法。

    总结一下FragmentManagerImpl的moveToState方法:
    1.首先Fragment创建时默认为INITIALIZING
    2.Activity调用相关的生命周期会调用Fragment的dispatchXXXX方法,该方法最终会调用到FragmentManagerImpl的moveToState方法,该方法会比较当前分发的状态与Fragment的当前状态,如果当前Fragment状态小于分发的状态则会走if代码块,否则会走else代码块。
    3.在每个switch的case块中都没有break,依旧是要遍历所有的case代码块,但如果当前fragment的状态小于等于分发的状态时才会执行相关case中的if代码块,调用相关的fragment声明周期。大于时则走else的代码块,逻辑与if代码块类似,只是Fragment的mState会依次减少
    4.if:Fragment的mState自增(onCretae---》onResumse),else:Fragment的mState自减(onResume---->>onDestory)

    流程图总结如下:


    image.png

    相关文章

      网友评论

        本文标题:Fragment(AndroidX版本)源码解析(一)

        本文链接:https://www.haomeiwen.com/subject/rswloltx.html