Android开发

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

2021-10-12  本文已影响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
上一篇下一篇

猜你喜欢

热点阅读