通常情况下我们使用fragment的方式是这样的:
FragmentManager mFragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();
fragmentTransaction.add(mContainerViewId, fragment);
fragmentTransaction.commit();
那么Fragment是如果创建的,如何被添加到布局中的呢,我们一起来分析下系统是如何做的。
通过点击add
、beginTransaction
可以发现都是抽象方法,那么只能通过getFragmentManager()
首先获得 FragmentManager
:
public FragmentManager getFragmentManager() {
return mFragments.getFragmentManager();
}
final FragmentManagerImpl mFragmentManager = new FragmentManagerImpl();
最终可以获得FragmentManagerImpl
这个FragmentMananger实现类。
// FragmentManagerImpl.java
@Override
public FragmentTransaction beginTransaction() {
return new BackStackRecord(this);
}
// BackStackRecord.java
public FragmentTransaction add(Fragment fragment, String tag) {
doAddOp(0, fragment, tag, OP_ADD);
return this;
}
public FragmentTransaction add(int containerViewId, Fragment fragment) {
doAddOp(containerViewId, fragment, null, OP_ADD);
return this;
}
public FragmentTransaction add(int containerViewId, Fragment fragment, String tag) {
doAddOp(containerViewId, fragment, tag, OP_ADD);
return this;
}
最终通过调用BackStackRecord的doAddOp(int containerViewId, Fragment fragment, String tag, int opcmd)
方法将fragment加入管理中。
private void doAddOp(int containerViewId, Fragment fragment, String tag, int opcmd) {
fragment.mFragmentManager = mManager;
Op op = new Op();
op.cmd = opcmd;
op.fragment = fragment;
addOp(op);
}
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++;
}
可以发现在add方法中,系统只做了赋值操作,并没有对fragment进行任何操作,所以应该是在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(Log.VERBOSE, TAG);
PrintWriter pw = new FastPrintWriter(logw, false, 1024);
dump(" ", null, pw, null);
pw.flush();
}
mCommitted = true;
if (mAddToBackStack) {
mIndex = mManager.allocBackStackIndex(this);
} else {
mIndex = -1;
}
mManager.enqueueAction(this, allowStateLoss);
return mIndex;
}
// FragmentManager.java
public int allocBackStackIndex(BackStackRecord bse) {
synchronized (this) {
if (mAvailBackStackIndices == null || mAvailBackStackIndices.size() <= 0) {
if (mBackStackIndices == null) {
mBackStackIndices = new ArrayList<BackStackRecord>();
}
int index = mBackStackIndices.size();
if (DEBUG) Log.v(TAG, "Setting back stack index " + index + " to " + bse);
mBackStackIndices.add(bse);
return index;
} else {
int index = mAvailBackStackIndices.remove(mAvailBackStackIndices.size()-1);
if (DEBUG) Log.v(TAG, "Adding back stack index " + index + " with " + bse);
mBackStackIndices.set(index, bse);
return index;
}
}
}
public void enqueueAction(Runnable action, boolean allowStateLoss) {
if (!allowStateLoss) {
checkStateLoss();
}
synchronized (this) {
mPendingActions.add(action);
if (mPendingActions.size() == 1) {
mHost.getHandler().removeCallbacks(mExecCommit);
mHost.getHandler().post(mExecCommit);
}
}
}
commit
方法最终调用了manager的allocBackStackIndex
和enqueueAction
方法,其中allocBackStackIndex
方法将BackStackRecord
添加到了mBackStackIndices
中,而enqueueAction
方法首先将实现了Runnable的BackStackRecord
添加到了mPendingActions
,之后调用了handler。
// FragmentManagerImpl.java
Runnable mExecCommit = new Runnable() {
@Override
public void run() {
execPendingActions();
}
};
public boolean execPendingActions() {
while (true) {
int numActions;
synchronized (this) {
numActions = mPendingActions.size();
if (mTmpActions == null || mTmpActions.length < numActions) {
mTmpActions = new Runnable[numActions];
}
mPendingActions.toArray(mTmpActions);
mPendingActions.clear();
mHost.getHandler().removeCallbacks(mExecCommit);
}
mExecutingActions = true;
for (int i=0; i<numActions; i++) {
mTmpActions[i].run();
mTmpActions[i] = null;
}
mExecutingActions = false;
didSomething = true;
}
doPendingDeferredStart();
return didSomething;
}
execPendingActions
方法首先将mPendingActions
赋值给了mTmpActions
,之后通过for循环调用run方法:
// BackStackRecord.java
public void run() {
//代码省略
Op op = mHead;
while (op != null) {
switch (op.cmd) {
case OP_ADD: {
Fragment f = op.fragment;
f.mNextAnim = op.enterAnim;
mManager.addFragment(f, false);
}
break;
case OP_REPLACE: {
Fragment f = op.fragment;
int containerId = f.mContainerId;
if (mManager.mAdded != null) {
for (int i = mManager.mAdded.size() - 1; i >= 0; i--) {
Fragment old = mManager.mAdded.get(i);
if (FragmentManagerImpl.DEBUG) {
Log.v(TAG,
"OP_REPLACE: adding=" + f + " old=" + old);
}
if (old.mContainerId == containerId) {
if (old == f) {
op.fragment = f = null;
} else {
if (op.removed == null) {
op.removed = new ArrayList<Fragment>();
}
op.removed.add(old);
old.mNextAnim = op.exitAnim;
if (mAddToBackStack) {
old.mBackStackNesting += 1;
if (FragmentManagerImpl.DEBUG) {
Log.v(TAG, "Bump nesting of "
+ old + " to " + old.mBackStackNesting);
}
}
mManager.removeFragment(old, mTransition, mTransitionStyle);
}
}
}
}
if (f != null) {
f.mNextAnim = op.enterAnim;
mManager.addFragment(f, false);
}
}
break;
// 代码省略
}
op = op.next;
}
mManager.moveToState(mManager.mCurState, mTransition,
mTransitionStyle, true);
if (mAddToBackStack) {
mManager.addBackStackState(this);
}
}
这个时候就用上了我们之前add
方法的opcmd字段,add
赋值的字段是OP_ADD
,所以可以看到直接调用了mManager.addFragment(f, false)
方法;而replace
方法赋值的字段是OP_REPLACE
,首先调用mManager.removeFragment(old, mTransition, mTransitionStyle)
方法将上一个fragment移除,之后再调用mManager.addFragment(f, false)
:
public void addFragment(Fragment fragment, boolean moveToStateNow) {
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 (fragment.mHasMenu && fragment.mMenuVisible) {
mNeedMenuInvalidate = true;
}
if (moveToStateNow) {
moveToState(fragment);
}
}
}
void moveToState(Fragment f) {
moveToState(f, mCurState, 0, 0, false);
}
这个时候调用的moveToState
方法就涉及到了Fragment的生命周期:
void moveToState(Fragment f, int newState, int transit, int transitionStyle,
boolean keepActive) {
switch (f.mState) {
case Fragment.INITIALIZING:
// fragment的onAttach方法
f.onAttach(mHost.getContext());
if (!f.mRetaining) {
// fragment的onCreate方法
f.performCreate(f.mSavedFragmentState);
} else {
f.restoreChildFragmentState(f.mSavedFragmentState, true);
f.mState = Fragment.CREATED;
}
if (f.mFromLayout) {
// fragment的onCreateView方法
f.mView = f.performCreateView(f.getLayoutInflater(
f.mSavedFragmentState), null, f.mSavedFragmentState);
if (f.mView != null) {
f.mView.setSaveFromParentEnabled(false);
if (f.mHidden) f.mView.setVisibility(View.GONE);
// fragment的onViewCreated方法
f.onViewCreated(f.mView, f.mSavedFragmentState);
}
}
//代码省略
}