原来一直只是使用Fragment,除了对一些常用API很熟悉外,对Fragment的内部原理还是不清楚,索性花了几天的时间,去阅读了Fragment相关的源码,从整体上对Fragment的框架有了一定深度的认识。当然,Fragment相关的类很多,Fragment内部的成员也很多,我目前还无法弄清楚Fragment的每一个细节,但整体上的正确认识有助于我们对细节的把握,也能对问题的查找、定位以及解决起到指导作用。这篇文章我准备先从Fragment被添加到Activity中的过程入手,观察一些相关的类和调用流程,然后针对一些具体的问题,在源码中找到解释做出总结。
从我们平常使用的动态添加Fragment说起,看一下其中是哪些类在起作用。
MyFragment f = new MyFragment();
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.content, f)
.commit();
其中getSupportFragmentManager()方法返回了一个FragmentManager对象。
先来看看mFragments这个成员,它是一个FragmentController对象。创建的时候还传入了一个继承FragmentHostCallback类的HostCallbacks对象。
//FragmentActivity.java
public FragmentManager getSupportFragmentManager() {
return mFragments.getSupportFragmentManager();
}
final FragmentController mFragments = FragmentController.createController(new HostCallbacks());
先来看下这个HostCallbacks对象,初始化的时候传入了调用FragmentController.createController(new HostCallbacks())的FragmentActivity的实例的引用。
//HostCallbacks.java
public HostCallbacks() {
super(FragmentActivity.this /*fragmentActivity*/);
}
构造器中只调用了父类的构造器,继续看HostCallbacks的父类FragmentHostCallback。构造器利用传进来的FragmentActivity的引用,为自己的成员变量赋值,可以看到,这个类的实例不仅持有了Activity的引用,还持有它的context,handler等。重点关注下mFragmentManager这个成员,它在HostCallbacks初始化的时候也初始化,是一个 FragmentManagerImpl对象。
//FragmentHostCallback.java
FragmentHostCallback(FragmentActivity 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;
}
private final Activity mActivity;
final Context mContext;
private final Handler mHandler;
final int mWindowAnimations;
final FragmentManagerImpl mFragmentManager = new FragmentManagerImpl();
/** The loader managers for individual fragments [i.e. Fragment#getLoaderManager()] */
private SimpleArrayMap mAllLoaderManagers;
/** Whether or not fragment loaders should retain their state */
private boolean mRetainLoaders;
/** The loader manger for the fragment host [i.e. Activity#getLoaderManager()] */
private LoaderManagerImpl mLoaderManager;
private boolean mCheckedForLoaderManager;
/** Whether or not the fragment host loader manager was started */
private boolean mLoadersStarted;
再回到开头final FragmentController mFragments = FragmentController.createController(new HostCallbacks());这句话,mFragments(FragmentController)初始化的时候传入了一个HostCallbacks对象,这个对象似乎拥有Activity的很多信息并且具有它的引用。接着进入createController(FragmentHostCallback< ? > callbacks)方法,它初始化了一个FragmentController对象,而且把传入的HostCallbacks对象赋值给了自己的成员mHost,也就是说这个对象也持有了Activity的引用和一些信息。
//FragmentController.java
public static final FragmentController createController(FragmentHostCallback> callbacks) {
return new FragmentController(callbacks);
}
private FragmentController(FragmentHostCallback> callbacks) {
mHost = callbacks;
}
现在出现了FragmentActivity、HostCallbacks、FragmentController,后面两个类的实例都持有了FragmentActivity实例的引用。
我们再回到FragmentActivity#getSupportFragmentManager(),它调用了mFragments的getSupportFragmentManager()方法。
//FragmentController.java
public FragmentManager getSupportFragmentManager() {
return mHost.getFragmentManagerImpl();
}
返回的就是上面说到重点关注的成员mFragmentManager,它是一个FragmentManagerImpl对象。
//FragmentHostCallback.java
FragmentManagerImpl getFragmentManagerImpl() {
return mFragmentManager;
}
这个内部类继承了FragmentManager类。
final class FragmentManagerImpl extends FragmentManager implements LayoutInflaterFactory
到这里,getsupportFragmentmanager()方法看完了,引出了HostCallbacks类,FragmentController类。
接下来看beginTransaction()返回了一个BackStackRecord对象,这个对象继承于FragmentTransaction,看来后面的操作都和BackStackRecord对象有关了。
//FragmentManager.java
@Override
public FragmentTransaction beginTransaction() {
return new BackStackRecord(this);
}
到目前为止,我们知道getsupportFragmentmanager()返回了一个FragmentManagerImpl,它继承了FragmentManager, beginTransaction()返回了一个BackStackRecord对象,它继承了FragmentTransaction。FragmentController内部持有HostCallbacks(持有FragmentActivity的很多信息,还持有一个重要的类FragmentManagerImpl),FragmentActivity的对Fragment的操作都是转交给FragmentController去处理,而FragmentController内部也是调用HostCallbacks持有的FragmentManagerImpl去进行实际的操作。看来FragmentManagerImpl这个类是和Fragment打交道的类。而BackStackRecord也是FragmentManagerImpl操作的一个工具。
BackStackRecord内部有一个Op静态内部类,这个类含有两个Op引用,所以可以构成双向链表(双向链表结构有助于增加被添加到回退栈的BackStackRecord对象的回退效率)。一个Op内部维护一个cmd操作数,一个fragment,还有一些动画相关的参数。
//BackStackRecord.java
static final class Op {
Op next;
Op prev;
int cmd;
Fragment fragment;
int enterAnim;
int exitAnim;
int popEnterAnim;
int popExitAnim;
ArrayList removed;
}
我们看一下得到BackStackRecord后一些典型操作,其实最终都是创建了一个新的Op对象,然后为cmd和fragment赋值并执行了addOp(op).
//BackStackRecord.java
public FragmentTransaction add(int containerViewId, Fragment fragment) {
doAddOp(containerViewId, fragment, null, OP_ADD);
return this;
}
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);
}
public FragmentTransaction remove(Fragment fragment) {
Op op = new Op();
op.cmd = OP_REMOVE;
op.fragment = fragment;
addOp(op);
return this;
}
public FragmentTransaction hide(Fragment fragment) {
Op op = new Op();
op.cmd = OP_HIDE;
op.fragment = fragment;
addOp(op);
return this;
}
addOp(op) 实际是把op加入双向链表尾部,一个BackStackRecord对象内部可能有肯多次对Fragment的操作,每一次操作都对应一个Op对象,并把Op对象加入双向链表中。
//BackStackRecord.java
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++;
}
一个BackStackRecord对象的重要成员成员和Op的cmd的值如下:
//BackStackRecord.java
static final int OP_NULL = 0;
static final int OP_ADD = 1;
static final int OP_REPLACE = 2;
static final int OP_REMOVE = 3;
static final int OP_HIDE = 4;
static final int OP_SHOW = 5;
static final int OP_DETACH = 6;
static final int OP_ATTACH = 7;
final FragmentManagerImpl mManager;
Op mHead;
Op mTail;
int mNumOp;
int mEnterAnim;
int mExitAnim;
int mPopEnterAnim;
int mPopExitAnim;
int mTransition;
int mTransitionStyle;
boolean mAddToBackStack;
boolean mAllowAddToBackStack = true;
String mName;
boolean mCommitted;
int mIndex = -1;
一个BackStackRecord中可能包含多个操作,每一个操作都以一个Op对象的形式保存在BackStackRecord双向链表中。当对Fragment操作完了之后,最后一步是执行BackStackRecord的commit()方法。
//BackStackRecord.java
public int commit() {
return commitInternal(false);
}
int commitInternal(boolean allowStateLoss) {
if (mCommitted) throw new IllegalStateException("commit already called");
if (FragmentManagerImpl.DEBUG) {
Log.v(TAG, "Commit: " + this);
LogWriter logw = new LogWriter(TAG);
PrintWriter pw = new PrintWriter(logw);
dump(" ", null, pw, null);
}
//一个BackStackRecord对象只能被提交一次
mCommitted = true;
if (mAddToBackStack) {
//大致过程是保存在了mManager的一个ArrayList中,为该BackStackRecord分配唯一index
mIndex = mManager.allocBackStackIndex(this);
} else {
mIndex = -1;
}
mManager.enqueueAction(this, allowStateLoss);
return mIndex;
}
最终调用了FragmentManagerImpl的enqueueAction(Runnable action, boolean allowStateLoss) ,回看BackStackRecord类声明才发现它实现了Runnable接口(那么它的run() 方法肯定很重要)。
//FragmentManagerImpl.java
public void enqueueAction(Runnable action, boolean allowStateLoss) {
if (!allowStateLoss) {
checkStateLoss();
}
synchronized (this) {
if (mDestroyed || mHost == null) {
throw new IllegalStateException("Activity has been destroyed");
}
if (mPendingActions == null) {
mPendingActions = new ArrayList();
}
//一个ArrayList成员,添加了传入的BackStackRecord对象
mPendingActions.add(action);
//可能会post一个mExecCommit,这里的mHost.getHandler()获得的就是Activity的Handler
//这里说一下,FragmentManagerImpl中mHost赋值的时机是在Activity的onCreate()方法被调用时
if (mPendingActions.size() == 1) {
mHost.getHandler().removeCallbacks(mExecCommit);
mHost.getHandler().post(mExecCommit);
}
}
}
mExecCommit是一个Runnable成员,被post之后进入主线程的队列,会执行execPendingActions()方法
//FragmentManagerImpl.java
Runnable mExecCommit = new Runnable() {
@Override
public void run() {
execPendingActions();
}
};
public boolean execPendingActions() {
if (mExecutingActions) {
throw new IllegalStateException("Recursive entry to executePendingTransactions");
}
if (Looper.myLooper() != mHost.getHandler().getLooper()) {
throw new IllegalStateException("Must be called from main thread of process");
}
boolean didSomething = false;
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);
}
//标记为正在执行
mExecutingActions = true;
//依次执行mPendingActions中BackStackRecord的run方法
for (int i=0; i
从beginTransaction()开始,我们获得了一个BackStackRecord对象,接着执行一系列对Fragment的操作,在BackStackRecord内部表现为新建一系列Op对象并为它们的cmd和fragment成员赋相应的值,然后添加到双向链表中。commit()之后,BackStackRecord对象作为一个Runnable被添加到了FragmentManagerImpl的mPendingActions中,并在合适的时机会在主线程中执行BackStackRecord的run()。 也就是说commit() 之后,FragmentManagerImpl管理着BackStackRecord,并交由主线程执行BackStackRecord的run()。
第一篇就说到这里,接下来会具体分析BackStackRecord的run()方法和FragmentManagerImpl的moveToState(5参数)方法,来看看Fragment的生命周期到底是如何和Activity交互的,最后还会针对Fragment的状态保存相关问题在源码中找寻答案。