Fragment解析(1)
-
写在前面
本文基于androidx相关源码,也就是在androidx.fragment.app包下面的相关类,基于继承自AppCompatActivity的使用,AppCompatActivity继承自FragmentActivity,而FragmentActivity内部管理着Fragment相关;如果是继承自Activity的则在Activity内部使用的是android.app包下的相关类,Activity里面也会有一个FragmentController对象mFragments,但它是android.app包下的,不是同一个类。调用Activity的相关方法时,这两个mFragments的逻辑都会执行,这种看似重复主要是为了兼容。
本文主要分析fragment的xml加载流程、生命周期以及在这个过程中和和Activity的联系。
-
建立连接
首先,需要建立Activity和Fragment的连接,在设计上,Activity并不是直接管理Fragment的,而是通过一个叫做FragmetnController的对象mFragements来管理:
final FragmentController mFragments = FragmentController.createController(new HostCallbacks());
在FragmentActivity的构造方法里会调用init方法:
private void init() { ... ... addOnContextAvailableListener(context -> mFragments.attachHost(null /*parent*/)); }
在这里添加了一个监听,addOnContextAvailableListener方法是在其父类ComponentActivity中定义的:
@Override public final void addOnContextAvailableListener( @NonNull OnContextAvailableListener listener) { mContextAwareHelper.addOnContextAvailableListener(listener); }
//ContextAwareHelper中: public void addOnContextAvailableListener(@NonNull OnContextAvailableListener listener) { if (mContext != null) { listener.onContextAvailable(mContext); } mListeners.add(listener); } public void dispatchOnContextAvailable(@NonNull Context context) { mContext = context; for (OnContextAvailableListener listener : mListeners) { listener.onContextAvailable(context); } }
在ComponentActivity的onCreate方法中会调用:
@Override protected void onCreate(@Nullable Bundle savedInstanceState) { ... ... mContextAwareHelper.dispatchOnContextAvailable(this); super.onCreate(savedInstanceState); ... ... }
因此,在Activity的onCreate时会调用mFragments.attachHost方法:
public void attachHost(@Nullable Fragment parent) { mHost.mFragmentManager.attachController( mHost, mHost /*container*/, parent); }
mHost就是传入的HostCallbacks。mFragmentManager在其父类FragmentHostCallback中定义:
final FragmentManager mFragmentManager = new FragmentManagerImpl();
/** * Package private implementation of FragmentManager. * <p> * All of the logic that used to be in this class has moved * to {@link FragmentManager} itself. * <p> * Developers should never instantiate a FragmentManager * directly, but instead operate via the APIs on * {@link FragmentActivity}, {@link Fragment}, or * {@link FragmentController} to retrieve an instance. */ class FragmentManagerImpl extends FragmentManager { }
这是个空实现,根据注释,我们知道逻辑都放在了FragmentManager中,在FragmentManager的attachController方法中:
void attachController(@NonNull FragmentHostCallback<?> host, @NonNull FragmentContainer container, @Nullable final Fragment parent) { if (mHost != null) throw new IllegalStateException("Already attached"); mHost = host; mContainer = container; mParent = parent; if (mParent != null) { addFragmentOnAttachListener(new FragmentOnAttachListener() { @SuppressWarnings("deprecation") @Override public void onAttachFragment(@NonNull FragmentManager fragmentManager, @NonNull Fragment fragment) { parent.onAttachFragment(fragment); } }); } else if (host instanceof FragmentOnAttachListener) { addFragmentOnAttachListener((FragmentOnAttachListener) host); } ... ... }
到这里,我们知道了每一个Activity都有自己独立的FragmentController,FragmentController持有独立的HostCallbacks,其父类中持有一个独立的FragmentManager实例,它的mContainer是HostCallbacks,因此每个Activity调用getSupportFragmentManager方法获取的FragmentManager都是属于当前Activity本身的。
至此,Activity和FragmentController关联起来了,下面看看Fragment是如何创建的。
我们知道,Fragment有两种创建方式,一种是通过xml定义,另一种是通过FragmentTransaction调用commit方法,下面我们分别从两个方向分析一下是如何实现的。
-
通过xml加载Fragment
我们知道,如果Fragment在xml中定义的话,就会走到LayoutInflater的inflate流程,在LayoutInflater的inflate解析流程(详情见《LayoutInflater解析》一文 )中,没有发现任何解析fragment标签的代码,但是在tryCreateView方法里预留了mFactory、mFactory2这样的接口实例,会自动调用它们的onCreateView方法,那Fragment是否是通过它们来从xml中加载的呢?
按照这个思路,根据tryCreateView内的调用顺序,mFactory2、mFactory和mPrivateFactory会被依次调用,如果前面的Factory创建出实例了则直接返回。mFactory2、mFactory和mPrivateFactory的赋值有两个途径,一个是在LayoutInflater的双参数的构造方法里通过克隆另一个LayoutInflater的Factory,另一种是通过相关的setXxx方法设置。在《LayoutInflater解析》中我们发现通过LayoutInflater.from方法获取的实例没有通过构造函数方式对Factory赋值,所以只能是在某个地方通过相关的set方法赋值的。
按照顺序,首先看看LayoutInflater的setFactory2方法会不会在哪里调用了呢?
搜了一下有很多地方,但是如果想要在加载布局的时候就已经可以使用Factory,通过分析,我们锁定了LayoutInflaterCompat的其中一个setFactory2重载方法:
public static void setFactory2( @NonNull LayoutInflater inflater, @NonNull LayoutInflater.Factory2 factory) { inflater.setFactory2(factory); if (Build.VERSION.SDK_INT < 21) { final LayoutInflater.Factory f = inflater.getFactory(); if (f instanceof LayoutInflater.Factory2) { // The merged factory is now set to getFactory(), but not getFactory2() (pre-v21). // We will now try and force set the merged factory to mFactory2 forceSetFactory2(inflater, (LayoutInflater.Factory2) f); } else { // Else, we will force set the original wrapped Factory2 forceSetFactory2(inflater, factory); } } }
为什么锁定这个方法,是因为我们发现这个方法会在AppCompatDelegateImpl的installViewFactory方法中调用,先看AppCompatDelegateImpl的构造函数:
@ContentView public AppCompatActivity(@LayoutRes int contentLayoutId) { super(contentLayoutId); initDelegate(); } private void initDelegate() { ... addOnContextAvailableListener(new OnContextAvailableListener() { @Override public void onContextAvailable(@NonNull Context context) { final AppCompatDelegate delegate = getDelegate(); delegate.installViewFactory(); ... } }); }
可以看到,在AppCompatActivity的构造函数里注册了Context监听:
@Override public final void addOnContextAvailableListener( @NonNull OnContextAvailableListener listener) { mContextAwareHelper.addOnContextAvailableListener(listener); }
在ComponentActivity的onCreate方法里会分发通知:
@Override protected void onCreate(@Nullable Bundle savedInstanceState) { ... mContextAwareHelper.dispatchOnContextAvailable(this); super.onCreate(savedInstanceState); ... }
我们知道,加载xml布局就是在setContenView流程里调用的,因此会先于加载xml布局调用installViewFactory方法,这符合我们前面的猜想需求:
@Override public void installViewFactory() { LayoutInflater layoutInflater = LayoutInflater.from(mContext); if (layoutInflater.getFactory() == null) { LayoutInflaterCompat.setFactory2(layoutInflater, this); } ... }
所以就是在这里设置的mFactory2,所以LayoutInflater的mFactory2是AppCompatDelegateImpl,查找了AppCompatDelegateImpl重写的onCreateView方法,里面并没有找到和fragment相关的解析代码,很显然这个类不是解析fragment相关类的地方。
于是我们只剩下了一个地方: mPrivateFactory !
经过查找(使用IDE自动关联无法跳转,用ctrl+H全局搜索),我们发现在Activity的attach方法里有一句:
mWindow.getLayoutInflater().setPrivateFactory(this);
PhoneWindow的构造方法里初始化了LayoutInflater:
public PhoneWindow(@UiContext Context context) { super(context); mLayoutInflater = LayoutInflater.from(context); ... }
之后PhoneWindow的setContentView逻辑中使用的mLayoutInflater正是这个已经初始化好的LayoutInflater:
public void setContentView(int layoutResID) { ... mLayoutInflater.inflate(layoutResID, mContentParent); ... }
回到xml加载流程中,由于FragmentActivity作为子类实现了它的onCreateView方法,因此此时mPrivateFactory.onCreateView方法就会走到FragmentActivity的onCreateView方法里,在它的实现里会调用dispatchFragmentsOnCreateView方法:
final View dispatchFragmentsOnCreateView(@Nullable View parent, @NonNull String name, @NonNull Context context, @NonNull AttributeSet attrs) { return mFragments.onCreateView(parent, name, context, attrs); }
public View onCreateView(@Nullable View parent, @NonNull String name, @NonNull Context context, @NonNull AttributeSet attrs) { return mHost.mFragmentManager.getLayoutInflaterFactory() .onCreateView(parent, name, context, attrs); }
getLayoutInflaterFactory得到的是FragmentManager的mLayoutInflaterFactory:
private final FragmentLayoutInflaterFactory mLayoutInflaterFactory = new FragmentLayoutInflaterFactory(this);
FragmentLayoutInflaterFactory的onCreateView方法如下:
public View onCreateView(@Nullable final View parent, @NonNull String name, @NonNull Context context, @NonNull AttributeSet attrs) { //首先会尝试创建FragmentContainerView,熟悉navigation的话会对他很熟悉 if (FragmentContainerView.class.getName().equals(name)) { return new FragmentContainerView(context, attrs, mFragmentManager); } //其次,加载<fragment/>标签 if (!"fragment".equals(name)) { return null; } //优先从fragment标签的class属性中取得Fragment的类名 String fname = attrs.getAttributeValue(null, "class"); TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.Fragment); //如果class属性没设置的话再从android:name中取Fragment的类名 if (fname == null) { fname = a.getString(R.styleable.Fragment_android_name); } //取到Fragment设置的id和tag(如果有的话) int id = a.getResourceId(R.styleable.Fragment_android_id, View.NO_ID); String tag = a.getString(R.styleable.Fragment_android_tag); a.recycle(); //必须是继承自Fragment的类 if (fname == null || !FragmentFactory.isFragmentClass(context.getClassLoader(), fname)) { // Invalid support lib fragment; let the device's framework handle it. // This will allow android.app.Fragments to do the right thing. 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、tag和containerId尝试从mFragmentManager中获取已有的Fragment Fragment fragment = id != View.NO_ID ? mFragmentManager.findFragmentById(id) : null; if (fragment == null && tag != null) { fragment = mFragmentManager.findFragmentByTag(tag); } if (fragment == null && containerId != View.NO_ID) { fragment = mFragmentManager.findFragmentById(containerId); } final FragmentStateManager fragmentStateManager; //如果FragmentManager中没找到则说明未创建过,则开始创建 if (fragment == null) { //没什么好说的,反射创建实例 fragment = mFragmentManager.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 = mFragmentManager; fragment.mHost = mFragmentManager.getHost(); fragment.onInflate(mFragmentManager.getHost().getContext(), attrs, fragment.mSavedFragmentState); fragmentStateManager = mFragmentManager.addFragment(fragment); if (FragmentManager.isLoggingEnabled(Log.VERBOSE)) { Log.v(FragmentManager.TAG, "Fragment " + fragment + " has been inflated via " + "the <fragment> tag: id=0x" + Integer.toHexString(id)); } } else if(...){...} else { // 如果已存在 fragment.mInLayout = true; fragment.mFragmentManager = mFragmentManager; fragment.mHost = mFragmentManager.getHost(); fragment.onInflate(mFragmentManager.getHost().getContext(), attrs, fragment.mSavedFragmentState); fragmentStateManager = mFragmentManager.createOrGetFragmentStateManager(fragment); } } ... fragment.mContainer = (ViewGroup) parent; // 其实如果是第一次加载的fragment的话,moveToExpectedState不会产生什么影响 fragmentStateManager.moveToExpectedState(); // 2) Create the Fragment's view despite not always moving to ACTIVITY_CREATED fragmentStateManager.ensureInflatedView(); ... if (id != 0) { fragment.mView.setId(id); } if (fragment.mView.getTag() == null) { fragment.mView.setTag(tag); } // Fragments added via the <fragment> tag cannot move above VIEW_CREATED // during inflation. Instead, we'll wait for the view to be attached to // window and its parent view and trigger moveToExpectedState() at that point. fragment.mView.addOnAttachStateChangeListener( new View.OnAttachStateChangeListener() { @Override public void onViewAttachedToWindow(View v) { Fragment fragment = fragmentStateManager.getFragment(); fragmentStateManager.moveToExpectedState(); SpecialEffectsController controller = SpecialEffectsController .getOrCreateController((ViewGroup) fragment.mView.getParent(), mFragmentManager); controller.forceCompleteAllOperations(); } @Override public void onViewDetachedFromWindow(View v) { } } ); return fragment.mView; }
可以看到,xml中定义的fragment标签就是在这里变成Fragment实例的,FragmentManager的findViewByXxx系列方法如下:
public Fragment findFragmentById(@IdRes int id) { return mFragmentStore.findFragmentById(id); } public Fragment findFragmentByTag(@Nullable String tag) { return mFragmentStore.findFragmentByTag(tag); } ...etc...
不管是按什么方式查找都是从mFragmentStore中取的,mFragmentStore是FragmentStore实例。
再来看addFragment方法:
FragmentStateManager addFragment(@NonNull Fragment fragment) { ... FragmentStateManager fragmentStateManager = createOrGetFragmentStateManager(fragment); fragment.mFragmentManager = this; mFragmentStore.makeActive(fragmentStateManager); if (!fragment.mDetached) { mFragmentStore.addFragment(fragment); fragment.mRemoving = false; if (fragment.mView == null) { fragment.mHiddenChanged = false; } if (isMenuAvailable(fragment)) { mNeedMenuInvalidate = true; } } return fragmentStateManager; }
mFragmentStore.addFragment方法如下:
void addFragment(@NonNull Fragment fragment) { if (mAdded.contains(fragment)) { throw new IllegalStateException("Fragment already added: " + fragment); } synchronized (mAdded) { mAdded.add(fragment); } fragment.mAdded = true; }
可见,fragment是被添加到FragmentStore的mAdded数组里了,findViewByXxx方法就是从这取的。makeActive方法把根据当前fragment创建的FragmentStateManager实例放入FragmentStroe的mActive中:
void makeActive(@NonNull FragmentStateManager newlyActive) { Fragment f = newlyActive.getFragment(); if (containsActiveFragment(f.mWho)) { return; } mActive.put(f.mWho, newlyActive); ... }
f.mWho是随机生成的UUID标志,确保唯一性。
然后会拿到当前fragment的FragmentStateManager(createOrGetFragmentStateManager方法会从FragmentStore中尝试取缓存中的,没取到就创建新的),然后调用它的moveToExpectedState方法:
void moveToExpectedState() { ... try { ... boolean stateWasChanged = false; int newState; while ((newState = computeExpectedState()) != mFragment.mState) { stateWasChanged = true; if (newState > mFragment.mState) { // 如果Fragment的state小于mFragmentManager的state了则生命周期方法往上依次调用,比如onAttach->onCreate->onCreateView... int nextStep = mFragment.mState + 1;//+1是因为状态是int,状态间差值为1 switch (nextStep) { case Fragment.ATTACHED: attach(); break; case Fragment.CREATED: create(); break; case Fragment.VIEW_CREATED: ensureInflatedView(); createView(); break; case Fragment.AWAITING_EXIT_EFFECTS: activityCreated(); break; case Fragment.ACTIVITY_CREATED: if (mFragment.mView != null && mFragment.mContainer != null) { SpecialEffectsController controller = SpecialEffectsController .getOrCreateController(mFragment.mContainer, mFragment.getParentFragmentManager()); int visibility = mFragment.mView.getVisibility(); SpecialEffectsController.Operation.State finalState = SpecialEffectsController.Operation.State.from(visibility); controller.enqueueAdd(finalState, this); } mFragment.mState = Fragment.ACTIVITY_CREATED; break; case Fragment.STARTED: start(); break; case Fragment.AWAITING_ENTER_EFFECTS: mFragment.mState = Fragment.AWAITING_ENTER_EFFECTS; break; case Fragment.RESUMED: resume(); break; } } else { // 如果Fragment的state超过mFragmentManager的state了则生命周期方法往下依次调用,比如onDestroyView->onCreateView... int nextStep = mFragment.mState - 1; switch (nextStep) { //同上 ... } } } if (!stateWasChanged && mFragment.mState == Fragment.INITIALIZING) { if (mFragment.mRemoving && !mFragment.isInBackStack() && !mFragment.mBeingSaved) { ... mFragment.initState(); } } ... } ... }
看一下computeExpectedState方法:
//In Fragment: static final int INITIALIZING = -1; // Not yet attached. static final int ATTACHED = 0; // Attached to the host. static final int CREATED = 1; // Created. static final int VIEW_CREATED = 2; // View Created. static final int AWAITING_EXIT_EFFECTS = 3; // Downward state, awaiting exit effects static final int ACTIVITY_CREATED = 4; // Fully created, not started. static final int STARTED = 5; // Created and started, not resumed. static final int AWAITING_ENTER_EFFECTS = 6; // Upward state, awaiting enter effects static final int RESUMED = 7; // Created started and resumed. //因为Fragment通常就是用来显示出来的,所以默认都是RESUMED,也是int值最大的状态 Lifecycle.State mMaxState = Lifecycle.State.RESUMED; //In FragmentStateManager: int computeExpectedState() { ... int maxState = mFragmentManagerState; // 每一个Fragment都有一个maxState,switch语句块是限制不能超过最大状态,其实就是生命周期长度的限制 switch (mFragment.mMaxState) { case RESUMED: // 如果mFragment.mMaxState是RESUMED,则mFragmentManagerState肯定不会超出,因为RESUMED是最大(最后的)的状态 break; case STARTED: maxState = Math.min(maxState, Fragment.STARTED); break; case CREATED: maxState = Math.min(maxState, Fragment.CREATED); break; case INITIALIZED: maxState = Math.min(maxState, Fragment.ATTACHED); break; default: maxState = Math.min(maxState, Fragment.INITIALIZING); } //如果是从xml中加载的情况 if (mFragment.mFromLayout) { if (mFragment.mInLayout) { //修改成至少是VIEW_CREATED状态 maxState = Math.max(mFragmentManagerState, Fragment.VIEW_CREATED); //此时还未创建mView,因此不会走下面的 if (mFragment.mView != null && mFragment.mView.getParent() == null) { maxState = Math.min(maxState, Fragment.VIEW_CREATED); } } else { ... } } ... return maxState; }
mFragmentManagerState是FragmentManager的状态,它由Activity来控制,当Activty相关生命周期方法触发FragmentManager的mFragmentManagerState状态改变时,其内部的每个Fragmetn都应该同步成和FragmentManager的状态一致,但是每个Fragment都有自己的maxState,标志着其当前状态不能超过这个状态,因此computeExpectedState方法就是根据限制获取一个合理范围内的状态。
继续往下看,如果新状态不是Fragment的当前状态,则需要把Fragment的状态更新到最新状态,通过 if (newState > mFragment.mState) 判断会走两个相反的分支(分别是创建和销毁两个方向的状态递进),因为Fragment的当前状态可能低于最新状态也可能超过了最新状态,又因为状态值用int型表示,于是通过 int nextStep = mFragment.mState + 1(或者-1) 来逐渐向新状态靠近,直到变成新状态。
在变成新状态的过程中,通过while循环,会逐渐调用过程中的生命周期方法,比如从初始化状态变成CREATED状态时会依次调用到attach、create方法,这些方法的内部分别会调用mFragment.performAttach、mFragment.performCreate方法,这些方法内又会分别调用到Fragment的onAttach、onCreate方法。因此,FragmentStateManager的moveToExpectedState方法是Fragment生命周期方法的触发入口。
因为我们通常是在调用完super.onCreate方法之后调用setContentView,所以mFragments的dispatchCreate方法是先执行的,因此在加载xml内容之前FragmentManager的state就变成了CREATED,所以computeExpectedState方法理应是该返回CREATED,但是if (mFragment.mFromLayout) 分支会把xml加载的状态变成VIEW_CREATED,这样while循环中其实会调用到createView,但是createView中其实此时不会去调用Fragment的onCreateView流程:
if (mFragment.mFromLayout) { // This case is handled by ensureInflatedView(), so there's nothing // else we need to do here. return; }
newState作为VIEW_CREATED回到while循环,很明显mFragment.mState需要从INITIALIZING变成VIEW_CREATED,所以这里会执行attach、create和createView方法,又因为createView方法不会执行任何从xml中加载的逻辑,所以此时只调用了onAttach和onCreate方法 。
至此,我们看到了onAttach、onCreate方法被调用了,还没有看到调用Fragment的onCreatView方法,而新创建的Fragment又不会走到moveToExpectedState的switch中的VIEW_CREATED状态分支那里调用createView,那么fragment的view又是在哪里产生的呢?
别着急,回到FragmentLayoutInflaterFactory的onCreateView方法,moveToExpectedState方法下一行执行了 fragmentStateManager.ensureInflatedView() :
void ensureInflatedView() { if (mFragment.mFromLayout && mFragment.mInLayout && !mFragment.mPerformedCreateView) { ... mFragment.performCreateView(mFragment.performGetLayoutInflater( mFragment.mSavedFragmentState), null, mFragment.mSavedFragmentState); if (mFragment.mView != null) { ... mFragment.mView.setTag(R.id.fragment_container_view_tag, mFragment); if (mFragment.mHidden) mFragment.mView.setVisibility(View.GONE); mFragment.performViewCreated(); ... mFragment.mState = Fragment.VIEW_CREATED; } } }
我们看到performCreateView方法在这里调用了,这个方法内部会调用:
mView = onCreateView(inflater, container, savedInstanceState);
可以看到,Fragment的onCreateView就是在这里调用的。然后会调用 mFragment.performViewCreated() 来回调onViewCreated方法。最后修改mFragment.mState为Fragment.VIEW_CREATED。
到这里,我们的xml加载Fragment过程就分析完了。
-
FragmentActivity的生命周期方法
在FragmentActivity中的生命周期方法中会调用FragmentController的相关方法通知Fragment的生命周期状态改变。
@Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); mFragmentLifecycleRegistry.handleLifecycleEvent(Lifecycle.Event.ON_CREATE); mFragments.dispatchCreate(); }
在FragmentActivity的onCreate方法中会调用mFragments的dispatchCreate方法,内部调用的是FragmentManager的dispatchCreate方法:
void dispatchCreate() { mStateSaved = false; mStopped = false; mNonConfig.setIsStateSaved(false); dispatchStateChange(Fragment.CREATED); }
其他的生命周期方法也是类似,都是在Activity的相关生命周期方法中调用的,比如,onActivityCreated和onStart都是在Activity的onStart方法中先后调用的:
@Override protected void onStart() { ... super.onStart(); ... if (!mCreated) { mCreated = true; mFragments.dispatchActivityCreated(); } mFragments.execPendingActions(); ... mFragments.dispatchStart(); }
最终会调用FragmentManager的dispatchActivityCreated方法和dispatchStart方法:
void dispatchActivityCreated() { mStateSaved = false; mStopped = false; mNonConfig.setIsStateSaved(false); dispatchStateChange(Fragment.ACTIVITY_CREATED); } void dispatchStart() { mStateSaved = false; mStopped = false; mNonConfig.setIsStateSaved(false); dispatchStateChange(Fragment.STARTED); }
可见最后都是调用dispatchStateChange方法,下面我们开始解析dispatchStateChange流程。
-
dispatchStateChange流程
private void dispatchStateChange(int nextState) { try { ... mFragmentStore.dispatchStateChange(nextState); moveToState(nextState, false); ... } finally { mExecutingActions = false; } execPendingActions(true); }
可以看到,这里首先会把mFragmentStore中mActive管理的FragmentStateManager的mFragmentManagerState都修改成新状态:
void dispatchStateChange(int state) { for (FragmentStateManager fragmentStateManager : mActive.values()) { if (fragmentStateManager != null) { fragmentStateManager.setFragmentManagerState(state); } } }
然后调用moveToState方法:
void moveToState(int newState, boolean always) { ... mCurState = newState; mFragmentStore.moveToExpectedState(); ... }
FragmentStroe的moveToExpectedState方法如下:
void moveToExpectedState() { for (Fragment f : mAdded) { FragmentStateManager fragmentStateManager = mActive.get(f.mWho); if (fragmentStateManager != null) { fragmentStateManager.moveToExpectedState(); } } for (FragmentStateManager fragmentStateManager : mActive.values()) { if (fragmentStateManager != null) { fragmentStateManager.moveToExpectedState(); ... } } }
可见,最终还是会调用每个FragmentStateManager的moveToExpectedState方法,这个方法我们之前已经分析过了,就是把其管理的Fragment的状态修改成和FragmentManager的状态一致,状态更改过程中会依次调用对应生命周期方法。
-
总结
-
xml中的Fragment是如何加载的
-
在Activity创建时调用的attach方法中会初始化PhoneWindow对象mWindow,mWindow初始化时会初始化一个LayoutInflater,然后会给这个LayoutInflater设置mPrivateFactory为Activity本身:
mWindow.getLayoutInflater().setPrivateFactory(this);
-
在进入Activity的onCreate方法之后,会调用setContentView方法,最终会调用到PhoneWindow的setContentView方法,在这个方法中会使用之前构造的LayoutInflater的inflate方法来完成xml布局的解析加载;
-
如果是fragment相关的标签,比如fragment标签或者androidx.fragment.app.FragmentContainerView等无法通过通用流程解析的标签,最终都会交给mPrivateFactory来处理;
-
通过第一步我们知道mPrivateFactory就是Activity本身,所以mPrivateFactory的onCreateView方法会被Activity的该方法执行,因为FragmentActivity继承了它,所以会走到FragmentActivity的onCreateView方法中;
-
FragmentActivity的onCreateView方法中会调用dispatchFragmentsOnCreateView方法,最终它会调用到一个叫FragmentLayoutInflaterFactory的onCreateView方法中,在这个方法里实现了解析fragment相关类的逻辑。
-
-
Fragment的生命周期方法触发顺序
- FragmentController的dispatchCreate方法会首先被调用,但此时因为还没有加载任何的fragment,所以此时只会修改FragmentManager的状态成CREATED;
- 然后setContentView的inflate流程开始,会把加载的fragment的状态都变成之前FragmentManager的状态,也就是CREATED(xml加载时computeExpectedState方法返回的是VIEW_CREATED,但是因为createView方法中不会执行从xml中加载这种情况的任何逻辑,所以虽然状态变了,但是onCreateView方法并没有调用);
- 状态改变过程通过while循环和fragment的state值+1(如果是销毁的过程则是-1)来实现的,比如从INITIALIZING变成CREATED会依次调用onAttached、onCreate;
- 根据第3步的算法,在第2步的过程中会调用到onAttach和onCreate方法,最后会调用ensureInflatedView方法触发onCreateView方法和onViewCreated方法;
- 上述两步都是Activity的onCreate中的工作,按照Activity的生命周期,接下来会调用onStart方法,它先会调用FragmentController的dispatchActivityCreated方法(只会调用一次),这会改变FragmentManager的状态变成ACTIVITY_CREATED,因此会调用onActivityCreated方法。然后还会调用dispatchStart方法触发onStart方法;
- 之后就是onResume,如果是销毁的过程也都是类似的流程。
-