作为一名 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(); } }同时为了方便起见,我大概介绍下我们即将遇到的几个类。第一次看的时候可能印象不深,但没关系,后面还会反复提起。
文/州轴走宙(简书作者) 原文链接:http://www.jianshu.com/p/f2fcc670afd6 著作权归作者所有,转载请联系作者获得授权,并标注“简书作者”。上面 UML 类图并不是完整的,但已经足够了。
ActivityThread : 大名鼎鼎的 Android 入口类,我们的分析也将会从它开始Instrumentation : ActivityThread 的得力助手,帮助 ActivityThread 触发 Activity 的生命周期MainActivity : 就是上文提到例子中的 MainActivity 类,继承自 ActivityHostCallbacks : Activity 的内部类,继承自 FragmentHostCallbackFragmentHostCallback : 持有 Handler、FragmentManagerImpl 等等对象的引用,别的对象可以通过持有它的引用间接控制 FragmentManagerImpl 等等对象FragmentController : Activity 通过控制它间接向 FragmentManagerImpl 发出命令FragmentManagerImpl : 顾名思义,它继承自 FragmentManager,用来对 Fragment 进行管理,在 FragmentHostCallback 中被初始化BackStackRecord : 继承自 FragmentTransation 并实现了 Runnable,每次调用 FragmentManager 对象的 beginTransaction() 方法都会产生一个 BackStackRecord 对象,可以将其理解为对 Fragment 的一系列操作(即事务)Op : 每次对 Fragment 的操作都会产生一个 Op 对象,其表示双向链表的一个结点哈哈,没印象无所谓...
那从哪里开始呢,我们注意到 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 列表中。将 Fragment 添加进 mAdded 列表中。设置 Fragment 的一些属性。然后到 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); //... } } //... } }这里做了两件事
虽然 mCurState 已经是 Fragment.CREATED 了,还是被再次赋了一次 Fragment.CREATED 值。(当然不是多余,这次只不过是特殊而已啦)和上次不同,这次 mActive 是非空的,那就遍历 mActive 取出 Fragment 作为参数并调用另一个 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(默认)。那么这里干了几件事。
Fragment 获得了 HostCallbacks 对象的引用。Fragment 再次获得 FragmentManagerImpl 的引用。调用了 Fragment 生命周期的第一个方法 onAttach!!因为 f.mParentFragment == null 为 true,所以会调用 mHost 的 onAttachFragment,进去看看 //HostCallback @Override public void onAttachFragment(Fragment fragment) { Activity.this.onAttachFragment(fragment); } 也就说 Activity 可以通过这个方法知道被依附的 Fragment 的实例。因为 !f.mRetaining 为 true,所以会接着调用 Fragment 的 performCreate 方法 //Fragment void performCreate(Bundle savedInstanceState) { //... onCreate(savedInstanceState); //... } 这里终于调用了 Fragment 的生命周期 onCreate 方法!!方法最后改变了 Fragment 的状态,即 f.mState = newState = Fragment.CREATED。有个容易忽略的细节就是,在每个 case 块的最后是没有 break 关键字的(可不是我忽略掉的喔,你看之前那 switch 块就有 break 关键字),也就是说只要符合条件会继续到下一个 case 块执行。在 Activity 的 performCreate 方法中调用了 onCreate 方法后,做了如上操作。主要做了两件最关注的事:
改变了 FragmentManagerImpl 的 mCurState 为 Fragment.CREATED。先切换到主线程后先后调用了 Fragment 的生命周期方法 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(默认),那从代码一步一步来看这里做了几件事。
通过 ID 取出装载 Fragment 的容器并赋给 container(看到这里是不是很激动)通过调用 f.performCreateView 获取到 View 并赋给 f.mView,那么 performCreateView 又是何方神圣? //Fragment View performCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { //... return onCreateView(inflater, container, savedInstanceState); } 哈哈,调用了我们 Fragment 的生命周期方法 onCreateView 方法!!然后当然是分别判断 f.mView、container 是否为非空以及是否有动画,有动画的话就启动动画,可以看到,这里是属性动画。最后就将 f.mView 添加到 container 中啦。我们下一个生命周期方法就要来啦,去看看 f.performActivityCreated //Fragment void performActivityCreated(Bundle savedInstanceState) { //... onActivityCreated(savedInstanceState); //... } onActivityCreated 终于出现啦,就这样,我们需要分析的生命周期方法都出来啦。方法最后一样改变了 Fragment 的状态,这次是 f.mState = newState = Fragment.ACTIVITY_CREATED通过 Activity 的 performCreateCommon 方法后,做了这么两件事:
改变了 FragmentManager 的 mCruState 为 Fragment.ACTIVITY_CREATED。接着 Fragment 的生命周期方法 onCreateView 被调用后将返回的 View 添加到指定容器中,随后就是另一个生命周期方法 onActivityCreated 方法,最后一样还会将 f.mState 改成最新的状态即 Fragment.ACTIVITY_CREATED。InStrumentation 对象通过 callActivityOnCreate 方法触发了 Activity 的 performCreate 后,Activity 也负责任地分别触发了 Fragment 的生命周期方法 onAttach、onCreate、onCreateView、onActivityCreated。经过了上面的分析,现在看这张图是不是不会觉得难记了?
其它生命周期方法逻辑没多大区别,每当 Activity 的生命周期方法被触发后它也会触发依附在它身上的 Fragment 的生命周期方法,感兴趣的朋友可以亲自去看看源码。
为了方便理解,我画了张思维导图,图片在此(超级大...)。
我再放上最开始那张类图,现在再看一遍,不知是不是印象深刻多了?