先看使用Fragment的简单例子,这里用Android support v4的源码:
Fragment fragment= new Fragment();
FragmentManager fragmentManager = getSupportFragmentManager();
fragmentManager.beginTransaction().add(R.id.container,fragment).commit();
进入FragmentActivity的getSupportFragmentManager方法:
public FragmentManager getSupportFragmentManager() {
return mFragments.getSupportFragmentManager();
}
final FragmentController mFragments = FragmentController.createController(new HostCallbacks());
可以看到FragmentManager是从FragmentController里取得的,那么看看FragmentController里有什么:
public class FragmentController {
public static final FragmentController
createController(FragmentHostCallback> callbacks) {
return new FragmentController(callbacks);
}
public FragmentManager getSupportFragmentManager() {
return mHost.getFragmentManagerImpl();
}
.........
}
又来了新类FragmentHostCallback,里面有个mFragmentManager变量:
public abstract class FragmentHostCallback extends FragmentContainer {
final FragmentManagerImpl mFragmentManager = new FragmentManagerImpl();
.........
}
看到这里,只要知道FragmentManager最后来自于FragmentManagerImpl就可以了,看名字知道是FragmentManager的实现类。
下面进入beginTransaction方法,在FragmentManagerImpl里找到:
public FragmentTransaction beginTransaction() {
return new BackStackRecord(this);
}
beginTransaction的作用就是返回一个BackStackRecord对象,可见事务办理都是交给了BackStackRecord这个类,这个类值得注意。
继续往下走,例子只是进行了add这个事务。查看BackStackRecord类里的add方法,有几个重载方法,最后都走到了其中一个,有空可以查看所有的源码,这里的主干代码是:
private void doAddOp(int containerViewId, Fragment fragment, String tag, int opcmd) {
fragment.mFragmentManager = mManager;
fragment.mTag = tag;
fragment.mContainerId = fragment.mFragmentId = containerViewId;
addOp(new Op(opcmd, fragment));//这里的opcmd是OP_ADD
}
只是设置了fragment的成员变量,然后调用addOp,注意opcmd,对fragment的操作有很多,这里是OP_ADD,常用的还有OP_REPLACE,OP_REMOVE,OP_HIDE,OP_SHOW等。addOp方法干了啥:
void addOp(Op op) {
mOps.add(op);
op.enterAnim = mEnterAnim;
op.exitAnim = mExitAnim;
op.popEnterAnim = mPopEnterAnim;
op.popExitAnim = mPopExitAnim;
}
ArrayList mOps = new ArrayList<>();
动画相关的不管,这步操作只是简单的将封装的ADD事务插入到ArrayList mOps里。现在准备工作做好了,到了最后一步,提交事务,调用commit()方法:
public int commit() {
return commitInternal(false);
}
int commitInternal(boolean allowStateLoss) {
mCommitted = true;
if (mAddToBackStack) {
mIndex = mManager.allocBackStackIndex(this);
} else {
mIndex = -1;
}
mManager.enqueueAction(this, allowStateLoss);
return mIndex;
}
这里流程只关注最后一句,由FragmentManager将之前的ADD操作加入队列。
一句话总结下上面的流程:将新建Fragment的事务封装成ADD操作交给FragmentManager,FragmentManager将ADD操作入队列。
下面看看入队列做了什么:
public void enqueueAction(OpGenerator action, boolean allowStateLoss) {
if (!allowStateLoss) {
checkStateLoss();
}
synchronized (this) {
if (mDestroyed || mHost == null) {
if (allowStateLoss) {
// This FragmentManager isn't attached, so drop the entire transaction.
return;
}
throw new IllegalStateException("Activity has been destroyed");
}
if (mPendingActions == null) {//PendingActions 是空,就新建一个
mPendingActions = new ArrayList<>();
}
mPendingActions.add(action);//ADD操作加入ArrayList
scheduleCommit();
}
}
enqueue意思是入队,但是这里其实是个列表,不用在意这些细节。加入队列,后面scheduleCommit的名字看起来就是提交这个列表,执行列表里的各个操作了,看看源码:
private void scheduleCommit() {
synchronized (this) {
boolean postponeReady =
mPostponedTransactions != null && !mPostponedTransactions.isEmpty();
boolean pendingReady = mPendingActions != null && mPendingActions.size() == 1;
if (postponeReady || pendingReady) {
mHost.getHandler().removeCallbacks(mExecCommit);
mHost.getHandler().post(mExecCommit);
}
}
}
又是通过Handler机制传递消息的。Handler从哪来的?mHost是什么?最开始的FragmentActivity里有个mHandler:
public class FragmentActivity extends BaseFragmentActivityApi16 implements
ActivityCompat.OnRequestPermissionsResultCallback,
ActivityCompat.RequestPermissionsRequestCodeValidator {
final FragmentController mFragments =
FragmentController.createController(new HostCallbacks());//mHost就是HostCallbacks,是FragmentHostCallback子类
final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
............
}
}
};
......
}
//activity.mHandler,Handler在这里
public abstract class FragmentHostCallback extends FragmentContainer {
FragmentHostCallback(FragmentActivity activity) {
this(activity, activity /*context*/, activity.mHandler, 0 /*windowAnimations*/);//mHandler就是FragmentActivity里的Handler
}
.........
}
好了,这里我们知道了mHost.getHandler().post(mExecCommit)的Handler是来自于FragmentActivity。这里有个问题scheduleCommit是在FragmentManager里调用的,FragmentManager的mHost为什么就是FragmentController的mHost呢?之后再分析,先看主流程,继续上面的:
mHost.getHandler().post(mExecCommit);//mExecCommit是个Runnable
Runnable mExecCommit = new Runnable() {
@Override
public void run() {
execPendingActions();
}
};
/**
* Only call from main thread!
*/
public boolean execPendingActions() {
ensureExecReady(true);
boolean didSomething = false;
while (generateOpsForPendingActions(mTmpRecords, mTmpIsPop)) {
mExecutingActions = true;
try {
removeRedundantOperationsAndExecute(mTmpRecords, mTmpIsPop);
} finally {
cleanupExec();
}
didSomething = true;
}
doPendingDeferredStart();
burpActive();
return didSomething;
}
private boolean generateOpsForPendingActions(ArrayList records,
ArrayList isPop) {
boolean didSomething = false;
synchronized (this) {
if (mPendingActions == null || mPendingActions.size() == 0) {
return false;
}
final int numActions = mPendingActions.size();
for (int i = 0; i < numActions; i++) {
didSomething |= mPendingActions.get(i).generateOps(records, isPop);//开始跑OP了
}
mPendingActions.clear();
mHost.getHandler().removeCallbacks(mExecCommit);
}
return didSomething;
}
这里mPendingActions.get(i).generateOps(records, isPop)的generateOps是个接口方法,找到mPendingActions列表中的元素是哪个类,看看generateOps具体实现,这里的mPendingActions.get(i)就是上面的ADD操作,是个BackStackRecord对象,所以看看BackStackRecord的generateOps方法:
/**
* Implementation of {@link FragmentManagerImpl.OpGenerator}.
* This operation is added to the list of pending actions during {@link #commit()}, and
* will be executed on the UI thread to run this FragmentTransaction.
*
* @param records Modified to add this BackStackRecord
* @param isRecordPop Modified to add a false (this isn't a pop)
* @return true always because the records and isRecordPop will always be changed
*/
@Override
final class BackStackState implements Parcelable {
public boolean generateOps(ArrayList records, ArrayList isRecordPop) {
records.add(this);//ADD加入records
isRecordPop.add(false);
if (mAddToBackStack) {
mManager.addBackStackState(this);
}
return true;
}
...........
}
看到这里知道了,generateOpsForPendingActions只是将mPendingActions里的元素加入到了mTmpRecords。那真正执行操作的应该就是removeRedundantOperationsAndExecute方法了:
//只贴主要代码
private void removeRedundantOperationsAndExecute(ArrayList records,
ArrayList isRecordPop) {
.............
final int numRecords = records.size();
int startIndex = 0;
for (int recordNum = 0; recordNum < numRecords; recordNum++) {
if (startIndex != recordNum) {
executeOpsTogether(records, isRecordPop, startIndex, recordNum);
}
}
.............
}
这里面又有很多调用,但是最终会回到每个BackStackRecord的executeOps()方法,executeOps就是个按操作类型执行各种具体动作的方法,比如OP_ADD,OP_REMOVE等等,看看OP_ADD操作干了什么:
void executeOps() {
final Fragment f = op.fragment;
switch (op.cmd) {
case OP_ADD:
f.setNextAnim(op.enterAnim);
mManager.addFragment(f, false); //第二个参数false,又回到了FragmentManager
break;
.............
}
if (!mReorderingAllowed) {
// Added fragments are added at the end to comply with prior behavior.
mManager.moveToState(mManager.mCurState, true);
}
}
final class FragmentManagerImpl extends FragmentManager implements LayoutInflater.Factory2 {
final ArrayList mAdded = new ArrayList<>();
public void addFragment(Fragment fragment, boolean moveToStateNow)
{
if (DEBUG) Log.v(TAG, "add: " + fragment);
makeActive(fragment);
if (!fragment.mDetached) {
if (mAdded.contains(fragment)) {
throw new IllegalStateException("Fragment already added: " + fragment);
}
synchronized (mAdded) {
mAdded.add(fragment);
}
fragment.mAdded = true;
fragment.mRemoving = false;
if (fragment.mView == null) {
fragment.mHiddenChanged = false;
}
if (fragment.mHasMenu && fragment.mMenuVisible) {
mNeedMenuInvalidate = true;
}
if (moveToStateNow) {//前面传来的是false,注意
moveToState(fragment);
}
}
}
//具体的Fragment操作都在FragmentManager里
public void removeFragment(Fragment fragment) {
..........
}
public void hideFragment(Fragment fragment) {
........
}
}
原来FragmentManager不过是将Fragment加入到自身的mAdded列表或者操作Fragment自身的属性,比如隐藏属性mHiddenChanged,具体查看其他几个方法就知道了。
再总结下上面一堆代码:将ADD操作加入FragmentManager的mPendingActions列表后提交,经过Handler机制在主线程中,执行ADD操作的executeOps方法,将新的Fragment插入到FragmentManager的mAdded列表。
走到这里,准备工作都做好了,下面该Fragment的生命周期上场了。因为传到addFragment的moveToStateNow是false,所以addFragment方法本身并没有走生命周期流程,回到executeOps方法,看到在最后调用了 mManager.moveToState。
下一篇Fragment源码简析(二)