先看使用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<E> extends FragmentContainer {
final FragmentManagerImpl mFragmentManager = new FragmentManagerImpl();
.........
}
看到這里奇昙,只要知道FragmentManager最后來自于FragmentManagerImpl就可以了娜饵,看名字知道是FragmentManager的實現(xiàn)類。
下面進入beginTransaction方法全封,在FragmentManagerImpl里找到:
public FragmentTransaction beginTransaction() {
return new BackStackRecord(this);
}
beginTransaction的作用就是返回一個BackStackRecord對象缺厉,可見事務辦理都是交給了BackStackRecord這個類,這個類值得注意。
繼續(xù)往下走恋拍,例子只是進行了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<Op> mOps = new ArrayList<>();
動畫相關的不管痕檬,這步操作只是簡單的將封裝的ADD事務插入到ArrayList mOps里■保現(xiàn)在準備工作做好了,到了最后一步梦谜,提交事務丘跌,調用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意思是入隊荒澡,但是這里其實是個列表蔼啦,不用在意這些細節(jié)。加入隊列仰猖,后面scheduleCommit的名字看起來就是提交這個列表捏肢,執(zhí)行列表里的各個操作了,看看源碼:
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<E> extends FragmentContainer {
FragmentHostCallback(FragmentActivity activity) {
this(activity, activity /*context*/, activity.mHandler, 0 /*windowAnimations*/);//mHandler就是FragmentActivity里的Handler
}
.........
}
好了辩棒,這里我們知道了mHost.getHandler().post(mExecCommit)的Handler是來自于FragmentActivity。這里有個問題scheduleCommit是在FragmentManager里調用的膨疏,F(xiàn)ragmentManager的mHost為什么就是FragmentController的mHost呢一睁?之后再分析,先看主流程,繼續(xù)上面的:
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<BackStackRecord> records,
ArrayList<Boolean> 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具體實現(xiàn),這里的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<BackStackRecord> records, ArrayList<Boolean> isRecordPop) {
records.add(this);//ADD加入records
isRecordPop.add(false);
if (mAddToBackStack) {
mManager.addBackStackState(this);
}
return true;
}
...........
}
看到這里知道了饲帅,generateOpsForPendingActions只是將mPendingActions里的元素加入到了mTmpRecords复凳。那真正執(zhí)行操作的應該就是removeRedundantOperationsAndExecute方法了:
//只貼主要代碼
private void removeRedundantOperationsAndExecute(ArrayList<BackStackRecord> records,
ArrayList<Boolean> 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就是個按操作類型執(zhí)行各種具體動作的方法育八,比如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); //第二個參數(shù)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<Fragment> 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) {//前面?zhèn)鱽淼氖莊alse,注意
moveToState(fragment);
}
}
}
//具體的Fragment操作都在FragmentManager里
public void removeFragment(Fragment fragment) {
..........
}
public void hideFragment(Fragment fragment) {
........
}
}
原來FragmentManager不過是將Fragment加入到自身的mAdded列表或者操作Fragment自身的屬性惶洲,比如隱藏屬性mHiddenChanged按声,具體查看其他幾個方法就知道了。
再總結下上面一堆代碼:將ADD操作加入FragmentManager的mPendingActions列表后提交湃鹊,經(jīng)過Handler機制在主線程中儒喊,執(zhí)行ADD操作的executeOps方法,將新的Fragment插入到FragmentManager的mAdded列表币呵。
走到這里怀愧,準備工作都做好了,下面該Fragment的生命周期上場了余赢。因為傳到addFragment的moveToStateNow是false,所以addFragment方法本身并沒有走生命周期流程芯义,回到executeOps方法,看到在最后調用了 mManager.moveToState。