Fragment加载到屏幕上的代码非常简单。getFragmentManager().beginTransaction().add(int addId,Fragment addFragment,String tag).commit();
首先看getFragmentMananger()方法:它定义在Activity中:
public FragmentManager getFragmentManager() {
return mFragments;
}
它只是直接返回了成员变量mFragments。这个变量的类型是FragmentManagerImpl.它是FragmentManager的子类。与FragmentManager和FragmentManagerState处于同一个文件中。而FragmentManager实际上是一个抽象类。
接着看第二个。beginTransaction():
public FragmentTransaction beginTransaction() {
return new BackStackRecord(this);
}
它将此FragmentManager本身赋给了一个叫做BackStackRecord的类。并将此Manager的实例在内部用一个成员变量保存起来。用于做回退栈栈管理之类的操作。故名思义。这是用于做Fragment回退栈记录处理的类。接着往下看add方法。这个方法是定义在BackStackRecord类中。
public FragmentTransaction add(int containerViewId, Fragment fragment, String tag) {
doAddOp(containerViewId, fragment, tag, OP_ADD);
return this;
}
这个方法里面直接将成员变量交给一个叫做doAddOp的方法进行处理。再多传了一个标志位。用于区分add、remove、replace等操作:
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);
}
这个方法中进行了一些保护性的判断。并将containerViewId和tag赋给要添加的fragment.并将此fragment放于一个Op的容器类中。类似我们常用的ViewHolder。它定义在BackStackRecord类中。而在add方法中传过来的参数OP_ADD。将它保存在了op类中的cmd变量中。
static final class Op {
Op next;
Op prev;
int cmd;
Fragment fragment;
int enterAnim;
int exitAnim;
int popEnterAnim;
int popExitAnim;
ArrayList<Fragment> removed;
}
接着看addOp方法:
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++;
}
这个方法就是把封装了此fragment的op实例保存起来。并将设置的动画也加入其中。
到此add方法算是介绍完了。接下来是commit方法,它也是在BackStackRecord类中定义。
public int commit() {
return commitInternal(false);
}
此处直接调用类中的commitInternal方法。传一个false进入。而我们知道fragment提交时还有一个叫做commitAllowingStateLoss的方法。这个方法内部也是直接调用commitInternal方法。但是传入一个true进入:
int commitInternal(boolean allowStateLoss) {
if (mCommitted) throw new IllegalStateException("commit already called");
if (FragmentManagerImpl.DEBUG) Log.v(TAG, "Commit: " + this);
mCommitted = true;
if (mAddToBackStack) {
mIndex = mManager.allocBackStackIndex(this);
} else {
mIndex = -1;
}
mManager.enqueueAction(this, allowStateLoss);
return mIndex;
}
这个方法中将对此fragment进行入栈操作。使用FragmentManagerImpl对象的enqueueAction方法将将回退栈记录管理类传回去。
下面回到FragmentManagerImpl类中:
public void enqueueAction(Runnable action, boolean allowStateLoss) {
if (!allowStateLoss) {
checkStateLoss();
}
synchronized (this) {
if (mActivity == null) {
throw new IllegalStateException("Activity has been destroyed");
}
if (mPendingActions == null) {
mPendingActions = new ArrayList<Runnable>();
}