Android 通过源码解析 Fragment 启动过程
2016-09-14 14:29
597 查看
0x00
作为一名 Android 开发者,大家绝对都接触过 Fragment 开发,而且绝大多数人例如我一直都很难记住下图 Fragment 复杂的生命周期,更别说要将其与 Activity 的生命周期关联起来。死背是无法解决问题的,若我们能从源码的角度对 Fragment 的启动过程进行分析,就能达到事半功倍的效果。那么我们选择上图中的第一部分入手吧。
下面我将会分析 Fragment 这一部分的启动过程,剩下部分的逻辑没有多大差异,所用的 Android SDK 版本为 23。
0x01
一般情况下我们 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 类,继承自 Activity
HostCallbacks : Activity 的内部类,继承自 FragmentHostCallback
FragmentHostCallback : 持有 Handler、FragmentManagerImpl 等等对象的引用,别的对象可以通过持有它的引用间接控制 FragmentManagerImpl 等等对象
FragmentController : Activity 通过控制它间接向 FragmentManagerImpl 发出命令
FragmentManagerImpl : 顾名思义,它继承自 FragmentManager,用来对 Fragment 进行管理,在 FragmentHostCallback 中被初始化
BackStackRecord : 继承自 FragmentTransation 并实现了 Runnable,每次调用 FragmentManager 对象的
beginTransaction()方法都会产生一个 BackStackRecord 对象,可以将其理解为对 Fragment 的一系列操作(即事务)
Op : 每次对 Fragment 的操作都会产生一个 Op 对象,其表示双向链表的一个结点
哈哈,没印象无所谓...
0x02
那从哪里开始呢,我们注意到 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 的实例化这里开始讲起吧
0x03
上文说到,Activity 会在 ActivityThread 的方法performLaunchActivity中通过反射实例化,相当于调用了它的无参构造方法,接着会触发 Activity 的成员变量 mFragments 的初始化,即
//Activity final FragmentController mFragments = FragmentController.createController(new HostCallbacks());
直接实例化了一个 HostCallbacks 对象并将其作为参数传入 FragmentController 类的
createController静态方法中。
I
好的,我们先看看 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。
II
上一节后我们已经有了一个 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 对象。
0x04
在 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 对象的引用。0x05
我们知道 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 : 下面是一连串的调用,先休息下,揉揉眼睛,喝喝水吧。
I
因为 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(); }
这个方法做了挺多操作的,我们还是一个一个来哈。
I-I
首先调用了父类 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 了
I-II
MainActivity 的父类的onCreate方法执行完后我们该关注
getFragmentManager方法了,到 Activity 中看看这个方法吧。
//Activity public FragmentManager getFragmentManager() { return mFragments.getFragmentManager(); } //FragmentController public FragmentManager getFragmentManager() { return mHost.getFragmentManagerImpl(); }
只是直接返回 HostCallbacks 对象持有的 FragmentManagerImpl 对象而已。
I-III
接下来就到了 FragmentManagerImpl 的beginTransaction方法了。
//FragmentManagerImpl public FragmentTransaction beginTransaction() { return new BackStackRecord(this); }
如我们所知,BackStackRecord 对象代表一系列对 Fragment 的操作,即事务,这里调用了 BackStackRecord 的构造方法并将 FragmentManagerImpl 自己作为参数传入。咱去看看构造方法做了啥。
//BackStackRecord public BackStackRecord(FragmentManagerImpl manager) { mManager = manager; }
这样 BackStackRecord 也持有了 FragmentManagerImpl 对象的引用。
I-Ⅳ
然后调用 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 表示的是双向链表的一个结点,这里得到了证实。这个方法只是双向链表的创建及添加结点逻辑。
I-V
可以提交事务了,即调用了 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 块执行。
I-小结
在 Activity 的performCreate方法中调用了
onCreate方法后,做了如上操作。主要做了两件最关注的事:
改变了 FragmentManagerImpl 的 mCurState 为 Fragment.CREATED。
先切换到主线程后先后调用了 Fragment 的生命周期方法
onAttach、
onCreate并将 Fragment 的状态即
mState 改为了 Fragment.CREATED。
II
那么就到了 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
II-小结
通过 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 的生命周期方法,感兴趣的朋友可以亲自去看看源码。
0x06
为了方便理解,我画了张思维导图,图片在此(超级大...)。我再放上最开始那张类图,现在再看一遍,不知是不是印象深刻多了?
相关文章推荐
- Android源码解析四大组件系列(一)---Service的启动过程分析
- 从源码角度解析android APP启动过程中各类及其方法的调用
- 通过AS调试android源码 看Activity的启动过程(1)
- Android源码解析四大组件系列(二)---Activity启动过程的总体把握
- Android Activity的启动过程源码解析
- Android源码解析之应用程序内部启动Activity过程(startActivity)的源代码分析
- Android 插件化开发——应用的启动过程源码解析(简单清晰)
- Android源码解析之Dalvik虚拟机的启动过程分析
- Android源码解析之新进程中启动自定义服务过程(startService)的原理分析
- Android应用程序的启动过程源码解析—点击图标启动过程
- Android源码解析四大组件系列(三)---Activity启动过程之ActivityThread是如何运行起来的
- Android源码解析之Zygote启动过程的源代码分析
- Android输入管理服务启动过程源码分析
- Android JB 4.2 中InputManager 启动过程解析 -- 1
- Android 4.0 Launcher2源码分析——启动过程分析
- Android 4.0 Launcher2源码分析——启动过程分析
- android启动过程配置文件的解析与语法
- [android源码分析]bluez启动过程中的各种plugin的初始化(一)--__bluetooth_builtin数组所耍的花样
- Tomcat 启动过程源码解析(一)
- Android SurfaceFlinger服务启动过程源码分析