作为一名 Android 开发者,大家绝对都接触过 Fragment 开发,而且绝大多数人例如我一直都很难记住下图 Fragment 复杂的生命周期,更别说要将其与 Activity 的生命周期关联起来。
死背是无法解决问题的,若我们能从源码的角度对 Fragment 的启动过程进行分析,就能达到事半功倍的效果。那么我们选择上图中的第一部分入手吧。
下面我将会分析 Fragment 这一部分的启动过程,剩下部分的逻辑没有多大差异,所用的 Android SDK 版本为 23 。
一般情况下我们 MainActivity 需要显示一个 ContentFragment,代码可以这么写。
//MainActivity public class MainActivity extends Activity{ ContentFragment mContentFragment; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mContentFragment = ContentFragment.newInstance(null); getFragmentManager() .beginTransaction() .replace(R.id.container,mContentFragment) .commit(); } }
同时为了方便起见,我大概介绍下我们即将遇到的几个类。第一次看的时候可能印象不深,但没关系,后面还会反复提起。
上面 UML 类图并不是完整的,但已经足够了。
beginTransaction()
方法都会产生一个 BackStackRecord 对象,可以将其理解为对 Fragment 的一系列操作(即事务) 哈哈,没印象无所谓...
那从哪里开始呢,我们注意到 Activity 类中有个 FragmentController 实例,那它是怎么初始化的?我们直接在 Activity 中搜索 FragmentController 关键字,即可找到如下代码:
//Activity final FragmentController mFragments = FragmentController.createController(new HostCallbacks());
原来在声明成员变量的同时初始化的呀,那也就是说在 Activity 被实例化时该成员变量也会被初始化,那么 Activity 又是在哪里被实例化的呢?作为一位看过 Activity 启动过程源码解析的男人,一下子就能想到 ActivityThread 的 performLaunchActivity
方法(当然,没看过 Activity 启动过程源码的朋友也没事,这篇文章分析的流程比那个简单多了,而且我们这里并不关注 Activity 的启动过程,看了这个或许对看那个有一定帮助),那我们去 ActivityThread 类的 performLaunchActivity
方法找下吧
//ActivityThread Activity activity = null; try { java.lang.ClassLoader cl = r.packageInfo.getClassLoader(); activity = mInstrumentation.newActivity(cl, component.getClassName(), r.intent); /*这个方法最终会通过反射调用 Activity 的无参构造方法*/ //... } catch (Exception e) { //... } //上面代码省略了一些非本次该关注的逻辑,下同
我们从 Activity 的实例化这里开始讲起吧
上文说到,Activity 会在 ActivityThread 的方法 performLaunchActivity
中通过反射实例化,相当于调用了它的无参构造方法,接着会触发 Activity 的成员变量 mFragments 的初始化,即
//Activity final FragmentController mFragments = FragmentController.createController(new HostCallbacks());
直接实例化了一个 HostCallbacks 对象并将其作为参数传入 FragmentController 类的 createController
静态方法中。
好的,我们先看看 HostCallbacks 初始化做了啥。
//HostCallbacks(因为 HostCallbacks 是 Activity 的内部类,所以是在 Activity.java 文件里) public HostCallbacks() { super(Activity.this ); }
嗯,因为 HostCallbacks 是 Activity 的内部类,所以直接用 Activity.this
作为参数调用它父类的构造方法,通过上文我们知道它的父类是 FragmentHostCallback
//FragmentHostCallback FragmentHostCallback(Activity activity) { this(activity, activity /*context*/, activity.mHandler, 0 /*windowAnimations*/); } FragmentHostCallback(Activity activity, Context context, Handler handler, int windowAnimations) { mActivity = activity; mContext = context; mHandler = handler; mWindowAnimations = windowAnimations; }
我们可以了解到它最终调用了 FragmentHostCallback 四个参数的重载构造方法,并会将 Activity 、Handler 等等对象保存到它的成员变量中。上文说到 FragmentManagerImpl 会在 FragmentHostCallback 中被初始化,看来它不是在构造方法中被初始化,那我们到成员变量的声明处看看吧。
//FragmentHostCallback final FragmentManagerImpl mFragmentManager = new FragmentManagerImpl();
又是在声明的同时初始化。FragmentManagerImpl 继承自抽象类 FragmentManager,FragmentManagerImpl 采用的是默认的构造方法,所以这部分的分析就到此为止了。对了,FragmentManagerImpl 和 FragmentManager 两个类都是在 FragmentManager.java
文件中的,而且不是内外部类关系,FragmentManagerImpl 类的声明如下
//FragmentManager final class FragmentManagerImpl extends FragmentManager implements LayoutInflater.Factory2{ //... }
作用域是包级的,包名是 android.app
。
上一节后我们已经有了一个 HostCallback 对象,并将其作为参数传给 FragmentController 的 createController
静态方法,我们现在进去看看吧。
//FragmentController public static final FragmentController createController(FragmentHostCallback<?> callbacks) { return new FragmentController(callbacks); } private FragmentController(FragmentHostCallback<?> callbacks) { mHost = callbacks; }
原来 FragmentController 隐藏了自己的构造方法, createController
就如同工厂方法,最后令 FragmentController 对象持有了 HostCallbacks 对象的引用。这样 FragmentController 就能通过 HostCallbacks 对象的引用来间接调用 FragmentManagerImpl 了啦,因为你看上面 FragmentHostCallback 类中 mFragmentManager 的声明也是默认包级的。
在 Activity 实例化的过程中,初始化了它的成员变量 FragmentController,FragmentController 持有了 HostCallbacks 对象的引用,HostCallbacks 是 Activity 的内部类,HostCallbacks 用 Activity 对象作为参数调用自己父类 FragmentHostCallback 的构造方法,接着 FragmentHostCallback 会持有了 Activity、Handler 等等对象的引用,并在声明 mFragmentManager 成员变量的同时实例化 FragmentManagerImpl 对象。
在 ActivityThread 类的 performLounchActivity
方法里 Activity 被实例化后不久会被调用重量级的 attach
方法,我们试试到这方法下看看是否有我们需要的信息。
//Activity mFragments.attachHost(null /*parent*/);
我们知道 mFragments 就是 FragmentController 对象的引用,看来这里确实有些初始化操作,那为什么是传入 null 呢?我们看下方法吧。
//FragmentManagerImpl public void attachHost(Fragment parent) { mHost.mFragmentManager.attachController( mHost, mHost /*container*/, parent); }
因为 Fragment 下也能有自己的子 Fragment,而现在我们的 Fragment 是在 Activity 下的,所以这里当然就直接传入 null 啦。我们再注意到本方法调用了 mHost 的 mFragmentManager 成员变量的 attachController
方法,我们只需关心方法的 第一个 参数。
//FragmentManagerImpl public void attachController(FragmentHostCallback<?> host, FragmentContainer container, Fragment parent) { if (mHost != null) throw new IllegalStateException("Already attached"); mHost = host; mContainer = container; mParent = parent; }
嗯,现在 FragmentManagerImpl 对象也持有了 HostCallbacks 对象的引用。
这一部分我们关注的仅仅是 FragmentManagerImpl 对象持有了 HostCallbacks 对象的引用。
我们知道 Fragment 的生命周期与 Acitivty 的有对应关系,那么我们也就可以猜到 Activity 的生命周期方法被触发时,Activity 会同时触发 Fragment 对应的生命周期方法,而且是通过自己持有的 FragmentController 对象来触发的,我们来看看是不是这样子吧。Activity 生命周期第一个被调用的方法是 onCreate
方法,它是在哪里被触发的呢?现在就是 ActivityThread 的得力助手 Instrumentation 出场的时候了!
还是在 ActivityThread 的 performLounchActivity
方法中,我们发现如下代码
//ActivityThread mInstrumentation.callActivityOnCreate(activity, r.state);
跳去 Instrumentation 类看看
//Instrumentation public void callActivityOnCreate(Activity activity, Bundle icicle) { //... activity.performCreate(icicle); //... }
调用了 performCreate
方法,注意这里的 activity 的运行时类型是 MainActivity,因为我们的 MainActivity 继承了 Activity,但 performCreate
方法是 final 的,MainActivity 无法重写,所以调用了其父类 Activity 的 performCreate
方法,我们去看下
//Activity final void performCreate(Bundle icicle) { onCreate(icicle); //... performCreateCommon(); }
先调用 onCreate
方法再调用 performCreateCommon
方法,同时我们注意到 onCreate
方法最先被调用而 performCreateCommon
最后被调用,两个方法都会分别触发 Fragment 的生命周期方法,这样安排是有目的的。下面我们分别分析。
PS : 下面是一连串的调用,先休息下,揉揉眼睛,喝喝水吧。
因为 MainActivity 重写了 Activity 的 onCreate
方法,我们先再看下我们重写的 onCreate
方法。
//MainActivity protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mContentFragment = ContentFragment.newInstance(null); getFragmentManager() .beginTransaction() .replace(R.id.container,mContentFragment) .commit(); }
这个方法做了挺多操作的,我们还是一个一个来哈。
首先调用了父类 Activity 的 onCreate
方法,我们去看看做了啥。
//Activity @MainThread @CallSuper protected void onCreate(@Nullable Bundle savedInstanceState) { //... mFragments.dispatchCreate(); //... }
Activity 好懒哟,又让人家 FragmentController 干活,可怜的 FragmentController
//FragmentController public void dispatchCreate() { mHost.mFragmentManager.dispatchCreate(); }
FragmentController 深得 Activity 精髓,把活推给了 FragmentManagerImpl,原来 FragmentManagerImpl 才是苦力。
//FragmentManagerImpl public void dispatchCreate() { //... moveToState(Fragment.CREATED, false); } void moveToState(int newState, boolean always) { moveToState(newState, 0, 0, always); } void moveToState(int newState, int transit, int transitStyle, boolean always) { if (mHost == null && newState != Fragment.INITIALIZING) { throw new IllegalStateException("No activity"); } if (!always && mCurState == newState) { return; } mCurState = newState; if (mActive != null) { //... } }
上面有三个方法被顺序调用,到了最后一个 moveToState
方法时我们只需关注它的参数 newState = Fragment.CREATED 、 always = false ,而默认情况下成员变量 mCurState = Fragment.INITIALIZING 、 mActive = null ,所以该方法执行后只有一个值得我们关注的细节 mCurState = Fragment.CREATED 了
MainActivity 的父类的 onCreate
方法执行完后我们该关注 getFragmentManager
方法了,到 Activity 中看看这个方法吧。
//Activity public FragmentManager getFragmentManager() { return mFragments.getFragmentManager(); } //FragmentController public FragmentManager getFragmentManager() { return mHost.getFragmentManagerImpl(); }
只是直接返回 HostCallbacks 对象持有的 FragmentManagerImpl 对象而已。
接下来就到了 FragmentManagerImpl 的 beginTransaction
方法了。
//FragmentManagerImpl public FragmentTransaction beginTransaction() { return new BackStackRecord(this); }
如我们所知,BackStackRecord 对象代表一系列对 Fragment 的操作,即 事务 ,这里调用了 BackStackRecord 的构造方法并将 FragmentManagerImpl 自己作为参数传入。咱去看看构造方法做了啥。
//BackStackRecord public BackStackRecord(FragmentManagerImpl manager) { mManager = manager; }
这样 BackStackRecord 也持有了 FragmentManagerImpl 对象的引用。
然后调用 BackStackRecord 的 replace
方法,即
//BackStackRecord public FragmentTransaction replace(int containerViewId, Fragment fragment) { return replace(containerViewId, fragment, null); } public FragmentTransaction replace(int containerViewId, Fragment fragment, String tag) { if (containerViewId == 0) { throw new IllegalArgumentException("Must use non-zero containerViewId"); } doAddOp(containerViewId, fragment, tag, OP_REPLACE); return this; }
先调用 replace
两个参数的重载方法,在该方法里调用了 replace
三个参数的重载方法,同时参数 tag = null ,在这个方法里首先判断传进的用来装载 Fragment 的容器的 ID 是否有效,接着调用 doAddOpp
方法,它第三个参数传入了的是 OP_REPLACE 常量。这里注意它最后返回了 this ,也就是我们的链式调用的下一个方法还是 BackStackRecord 对象的,结合下面我们脑海就能很形象地产生 Op 双向链表的图像。
//BackStackRecord private void doAddOp(int containerViewId, Fragment fragment, String tag, int opcmd) { fragment.mFragmentManager = mManager; if (tag != null) { if (fragment.mTag != null && !tag.equals(fragment.mTag)) { throw new IllegalStateException("Can't change tag of fragment " + fragment + ": was " + fragment.mTag + " now " + tag); } fragment.mTag = tag; } if (containerViewId != 0) { if (fragment.mFragmentId != 0 && fragment.mFragmentId != containerViewId) { throw new IllegalStateException("Can't change container ID of fragment " + fragment + ": was " + fragment.mFragmentId + " now " + containerViewId); } fragment.mContainerId = fragment.mFragmentId = containerViewId; } Op op = new Op(); op.cmd = opcmd; op.fragment = fragment; addOp(op); }
在本方法首先让参数 fragment 持有 FragmentManagerImpl 的引用,接着就是判断参数 tag 和 containerViewId 是否有效并赋值给 fragment 的成员变量。最后 Op 对象终于出场了(此处应有掌声)。实例化了一个 OP 对象后改变了它成员变量 cmd 的值,这里是 OP_REPLACE ,接着让 Op 也持有 Fragment 对象的引用,最后就是将 Op 对象作为参数调用 addOp
方法。
//BackStackRecord void addOp(Op op) { if (mHead == null) { mHead = mTail = op; } else { op.prev = mTail; mTail.next = op; mTail = op; } op.enterAnim = mEnterAnim; op.exitAnim = mExitAnim; op.popEnterAnim = mPopEnterAnim; op.popExitAnim = mPopExitAnim; mNumOp++; }
前面我们说过 Op 表示的是双向链表的一个结点,这里得到了证实。这个方法只是双向链表的创建及添加结点逻辑。
可以提交事务了,即调用了 BackStackRecord 对象的 commit
方法。
//BackStackRecord public int commit() { return commitInternal(false); } int commitInternal(boolean allowStateLoss) { if (mCommitted) { throw new IllegalStateException("commit already called"); } //... mCommitted = true; if (mAddToBackStack) { mIndex = mManager.allocBackStackIndex(this); } else { mIndex = -1; } mManager.enqueueAction(this, allowStateLoss); return mIndex; }
最终调用了 commitInternal
方法,首先通过 mCommitted 判断是否已经提交过,因为默认为 false ,所以这里不会抛出错误,接着最重要的逻辑就是调用了 mManager.enqueueAction(this, allowStateLoss)
, mManager 就是FragmentManagerImpl 对象,方法 enqueueAction
的第一个参数是 Runnable 类,但这里的 this 不是 BackStackRecord 对象么?
//BackStackRecord final class BackStackRecord extends FragmentTransaction implements FragmentManager.BackStackEntry, Runnable{ //... }
看到了吧,BackStackRecord 实现了 Runnable,看来会有大事发生...
//FragmentManagerImpl public void enqueueAction(Runnable action, boolean allowStateLoss) { //... synchronized (this) { if (mDestroyed || mHost == null) { throw new IllegalStateException("Activity has been destroyed"); } if (mPendingActions == null) { mPendingActions = new ArrayList<Runnable>(); } mPendingActions.add(action); if (mPendingActions.size() == 1) { mHost.getHandler().removeCallbacks(mExecCommit); mHost.getHandler().post(mExecCommit); } } }
这里将 Runnable 装入了 mPendingActions 中,因为此时 mPendingActions.size() == 1 为 true ,所以最终会将 mExecCommit 成员变量压入 mHost 持有的来自 Activity 的 Handler 对象里。那么我们现在可以推断出 mExecCommit 也是 Runnable 类型,同时它会在 主线程 被调用。我们看看 mExecCommmit 是何方神圣。
//FragmentManagerImpl Runnable mExecCommit = new Runnable() { @Override public void run() { execPendingActions(); } };
原来它的作用就是为了切换到主线程然后执行它外部类即 FragmentManagerImpl 的 execPendingActions
方法而已。现在我假设这个 Runnable 对象会被马上被调用,实际可能需要排队...好,到 execPendingAcions
方法了。
//FragmentManagerImpl public boolean execPendingActions() { //... while (true) { int numActions; synchronized (this) { if (mPendingActions == null || mPendingActions.size() == 0) { break; } numActions = mPendingActions.size(); if (mTmpActions == null || mTmpActions.length < numActions) { mTmpActions = new Runnable[numActions]; } mPendingActions.toArray(mTmpActions); mPendingActions.clear(); mHost.getHandler().removeCallbacks(mExecCommit); } //... for (int i=0; i<numActions; i++) { mTmpActions[i].run(); mTmpActions[i] = null; } //... } //... }
本方法我们只需关注首先将 mPendingActions 里的 Runnable 对象转移到 mTmpActions 数组里,并依次调用 mTmpActions 数组保存的 Runnable 的 run
方法。我们知道这里指的就是 BackStackRecord 中的 run
方法。去看看吧
//BackStackRecord public void run() { //... Op op = mHead; while (op != null) { switch (op.cmd) { //... case OP_REPLACE: { Fragment f = op.fragment; int containerId = f.mContainerId; //... if (f != null) { f.mNextAnim = op.enterAnim; mManager.addFragment(f, false); } } break; //... } op = op.next; } mManager.moveToState(mManager.mCurState, mTransition,mTransitionStyle, true); //... }
这个方法其实很长的,但我们还是只要关注我们当前需要关注的逻辑就行啦。可以看到其实就是从头遍历 Op 双向链表,并通过判断 Op 对象里的 cmd 成员变量的值进行不同操作而已(其实这就是命令模式,可以看我的另一篇介绍设计模式的文章),这里我们只关注 OP_REPLACE 。首先取出 Op 中保存的 Fragment 对象作为参数调用 FragmentManagerImpl 对象的 addFragment
方法,最后又通过 FragmentManagerImpl 对象的 moveToState
方法改变状态,还是一步一步来。
PS : 咳咳,下面我还有几句话要说。哈哈,我画了张 思维导图 ,或许对照着看能更好地理解。
先看看 FragmentManagerImpl 的 addFragment
方法吧,注意这里第一个参数传入了 Fragment 对象,第二个参数传入 false 。
//FragmentManagerImpl public void addFragment(Fragment fragment, boolean moveToStateNow) { if (mAdded == null) { mAdded = new ArrayList<Fragment>(); } //... makeActive(fragment); if (!fragment.mDetached) { if (mAdded.contains(fragment)) { throw new IllegalStateException("Fragment already added: " + fragment); } mAdded.add(fragment); fragment.mAdded = true; fragment.mRemoving = false; //... if (moveToStateNow) { moveToState(fragment); } } }
这里做了几件事:
makeActive
方法将 Fragment 对象添加进 mActive 列表中。 然后到 FragmentManagerImpl 的 moveToState
方法了。我们只需关心它的第一个参数,即 mManager.mCurState ,我们知道这里的 mCurState 此时已经被赋值成了 Fragment.CREATED 。
//FragmentManagerImpl void moveToState(int newState, int transit, int transitStyle, boolean always) { //... mCurState = newState; if (mActive != null) { //.. for (int i=0; i<mActive.size(); i++) { Fragment f = mActive.get(i); if (f != null) { moveToState(f, newState, transit, transitStyle, false); //... } } //... } }
这里做了两件事
moveToState
方法。下面我们见识下这个方法吧(<- 大 BOSS)。方法很长,还是只关注我们需要那部分。 //FragmentManagerImpl void moveToState(Fragment f, int newState, int transit, int transitionStyle, boolean keepActive) { //... if (f.mState < newState) { //... switch (f.mState) { case Fragment.INITIALIZING: //... f.mHost = mHost; f.mParentFragment = mParent; f.mFragmentManager = mParent != null ? mParent.mChildFragmentManager : mHost.getFragmentManagerImpl(); f.mCalled = false; f.onAttach(mHost.getContext()); //... if (f.mParentFragment == null) { mHost.onAttachFragment(f); } if (!f.mRetaining) { f.performCreate(f.mSavedFragmentState); } f.mRetaining = false; if (f.mFromLayout) { //... } //... } f.mState = newState; }
首先注意这里 f.mState = Fragment.INITIALIZING(默认) 、 newState = Fragment.CREATED 、 mParent = null 、 f.mRetaining = false(默认) 、 f.mFromLayout = false(默认) 。那么这里干了几件事。
onAttach
!! onAttachFragment
,进去看看 //HostCallback @Override public void onAttachFragment(Fragment fragment) { Activity.this.onAttachFragment(fragment); }
也就说 Activity 可以通过这个方法知道被依附的 Fragment 的实例。 performCreate
方法 //Fragment void performCreate(Bundle savedInstanceState) { //... onCreate(savedInstanceState); //... }
这里终于调用了 Fragment 的生命周期 onCreate
方法!! 在 Activity 的 performCreate
方法中调用了 onCreate
方法后,做了如上操作。主要做了两件最关注的事:
onAttach
、 onCreate
并将 Fragment 的状态即 mState 改为了 Fragment.CREATED 。 那么就到了 Activity 的 performCreate
方法中最后调用的 performCreateCommon
方法了。
//Activity final void performCreateCommon() { //... mFragments.dispatchActivityCreated(); //... }
和上面一样,相同的逻辑,那么我们可以猜到下面其实也大同小异,那就全盘托出吧。
//ActivityController public void dispatchActivityCreated() { mHost.mFragmentManager.dispatchActivityCreated(); /*一样,调用了 FragmentManagerImpl 的 dispatchActivityCreated 方法*/ } //FragmentManagerImpl public void dispatchActivityCreated() { //... moveToState(Fragment.ACTIVITY_CREATED, false); /*现在传入的状态常量是 Fragment.ACTIVITY_CREATED*/ } //FragmentManagerImpl void moveToState(int newState, boolean always) { moveToState(newState, 0, 0, always); } //FragmentManagerImpl void moveToState(int newState, int transit, int transitStyle, boolean always) { //... /*mCurState 这里又被改成了 Fragment.ACTIVITY_CREATED*/ mCurState = newState; if (mActive != null) { //... for (int i=0; i<mActive.size(); i++) { /*一样,遍历 mActive,调用 moveToState,分别将 Fragment 作为参数传入 */ Fragment f = mActive.get(i); if (f != null) { moveToState(f, newState, transit, transitStyle, false); //... } } //... } } //FragmentManagerImpl //方法很长,不怕,我们在代码外分析 void moveToState(Fragment f, int newState, int transit, int transitionStyle, boolean keepActive) { //... if (f.mState < newState) { //... switch (f.mState) { //... case Fragment.CREATED: if (newState > Fragment.CREATED) { //... if (!f.mFromLayout) { ViewGroup container = null; if (f.mContainerId != 0) { container = (ViewGroup)mContainer.onFindViewById(f.mContainerId); if (container == null && !f.mRestored) { //... } } f.mContainer = container; f.mView = f.performCreateView(f.getLayoutInflater( f.mSavedFragmentState), container, f.mSavedFragmentState); if (f.mView != null) { //... if (container != null) { Animator anim = loadAnimator(f, transit, true, transitionStyle); if (anim != null) { anim.setTarget(f.mView); setHWLayerAnimListenerIfAlpha(f.mView, anim); anim.start(); } container.addView(f.mView); } //... f.onViewCreated(f.mView, f.mSavedFragmentState); } } f.performActivityCreated(f.mSavedFragmentState); //... } //... } } f.mState = newState; }
嗯,和我们猜的一样,最后还是调用了这个 moveToState
方法,因为现在我们的参数 newState = Fragment.ACTIVITY_CREATED 、 f.newState = Fragment.CREATED 、 f.mFromLayout = false(默认) ,那从代码一步一步来看这里做了几件事。
f.performCreateView
获取到 View 并赋给 f.mView ,那么 performCreateView
又是何方神圣? //Fragment View performCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { //... return onCreateView(inflater, container, savedInstanceState); }
哈哈,调用了我们 Fragment 的生命周期方法 onCreateView
方法!! f.performActivityCreated
//Fragment void performActivityCreated(Bundle savedInstanceState) { //... onActivityCreated(savedInstanceState); //... }
onActivityCreated
终于出现啦,就这样,我们需要分析的生命周期方法都出来啦。 通过 Activity 的 performCreateCommon
方法后,做了这么两件事:
onCreateView
被调用后将返回的 View 添加到指定容器中,随后就是另一个生命周期方法 onActivityCreated
方法,最后一样还会将 f.mState 改成最新的状态即 Fragment.ACTIVITY_CREATED 。 InStrumentation 对象通过 callActivityOnCreate
方法触发了 Activity 的 performCreate
后,Activity 也负责任地分别触发了 Fragment 的生命周期方法 onAttach
、 onCreate
、 onCreateView
、 onActivityCreated
。经过了上面的分析,现在看这张图是不是不会觉得难记了?
其它生命周期方法逻辑没多大区别,每当 Activity 的生命周期方法被触发后它也会触发依附在它身上的 Fragment 的生命周期方法,感兴趣的朋友可以亲自去看看源码。
为了方便理解,我画了张 思维导图 ,图片在此(超级大...)。
我再放上最开始那张类图,现在再看一遍,不知是不是印象深刻多了?
我看过很多作者写的源码解析,但这次是我第一次写源码解析,不知自己能否驾驭得当,不知能否让各位理解整个流程。如有不足,希望能在评论提出,十分感谢哈。如果觉得写得不错,不求打赏,能否稍微给我点个赞呢?