FragmentManager
如下代码:通过supportFragmentManager和Activity进行关联起来
supportFragmentManager.beginTransaction().add().replace().remove().remove().add().addToBackStack().commit()
supportFramgentManager 后由谁提供的呢?从源码中可以看出是由FragmentController提供的,FragmentController是在FragmentActivity创建的时候初始化的。
final FragmentController mFragments = FragmentController.createController(new HostCallbacks());public FragmentManager getSupportFragmentManager() {return mFragments.getSupportFragmentManager();}
我们再看一下FragmentActivity的生命周期方法:如下代码都调用了mFragments的dispatch方法,也就是说Fragment的生命周期管理委托给了FragmentController。
@Overrideprotected void onStart() {super.onStart();....mFragments.dispatchStart();}@Overrideprotected void onStop() {super.onStop();.....mFragments.dispatchStop();}protected void onResumeFragments() {mFragments.dispatchResume();}
再来看FragmentController的代码,如下可以看到FragmentController中的代码具体是FragmentHostCallback来实现的
public class FragmentController {private final FragmentHostCallback<?> mHost;public static FragmentController createController(FragmentHostCallback<?> callbacks) {return new FragmentController(callbacks);}private FragmentController(FragmentHostCallback<?> callbacks) {mHost = callbacks;}public FragmentManager getSupportFragmentManager() {return mHost.getFragmentManagerImpl();}....}
在进入FragmentHostCallback 中创建了FragmentManager,注意Fragments may be hosted by any object 这句话,fragment可以由任何对象托管。也就是说fragment可以应用在任何地方不一定在Activity中。
/*** Integration points with the Fragment host.* <p>* Fragments may be hosted by any object; such as an {@link Activity}. In order to* host fragments, implement {@link FragmentHostCallback}, overriding the methods* applicable to the host.*/public abstract class FragmentHostCallback<E> extends FragmentContainer {@Nullable private final Activity mActivity;@NonNull private final Context mContext;@NonNull private final Handler mHandler;private final int mWindowAnimations;final FragmentManagerImpl mFragmentManager = new FragmentManagerImpl();}
在FragmentActivity类中,实现了FragmentHostCallback抽象类:所以我们可以在Activity中管理fragment
class HostCallbacks extends FragmentHostCallback<FragmentActivity> {public HostCallbacks() {super(FragmentActivity.this /*fragmentActivity*/);}@Overridepublic void onDump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {FragmentActivity.this.dump(prefix, fd, writer, args);}@Overridepublic boolean onShouldSaveFragmentState(Fragment fragment) {return !isFinishing();}}
FragmentTransaction
FragmentTransaction 对fragment进行事务操作,所谓事务就是一次性进行多个操作。
如下代码进行了多个操作:add replace remove等操作
supportFragmentManager.beginTransaction().add().replace().remove().remove().add().addToBackStack().commit()
在FragmentManager中的方法
@Overridepublic FragmentTransaction beginTransaction() {return new BackStackRecord(this);}
调用了BackStackRecord 继承了FragmentTransaction,在操作fragment回退栈的时候能够逆向执行事务,从而实现fragment的出栈操作。
/*** Entry of an operation on the fragment back stack.*/final class BackStackRecord extends FragmentTransaction implementsFragmentManager.BackStackEntry, FragmentManagerImpl.OpGenerator {......}
事务操作就是在BackStackRecord中执行的,例如add操作,将fragment包装到Op包装类中,然后添加到list集合中,在提交事务的时候进行处理
//add 操作标记 OP_ADD@Overridepublic FragmentTransaction add(Fragment fragment, @Nullable String tag) {doAddOp(0, fragment, tag, OP_ADD);return this;}//replace操作 标记OP_REPLACE 添加到集合汇总@Overridepublic FragmentTransaction replace(int containerViewId, Fragment fragment,@Nullable String tag) {if (containerViewId == 0) {throw new IllegalArgumentException("Must use non-zero containerViewId");}doAddOp(containerViewId, fragment, tag, OP_REPLACE);return this;}//remove 操作 标记OP_REMOVE 添加到集合中@Overridepublic FragmentTransaction remove(Fragment fragment) {addOp(new Op(OP_REMOVE, fragment));return this;}ArrayList<Op> mOps = new ArrayList<>();//最终都调用了addOp方法void addOp(Op op) {mOps.add(op);op.enterAnim = mEnterAnim;op.exitAnim = mExitAnim;op.popEnterAnim = mPopEnterAnim;op.popExitAnim = mPopExitAnim;}
下面来看一下,事务提交commit操作如何处理的:
@Overridepublic int commit() {return commitInternal(false);}@Overridepublic int commitAllowingStateLoss() {return commitInternal(true);}int commitInternal(boolean allowStateLoss) {//如果mCommitted == true 抛出异常,对于一个事物提交最多只能调用一次if (mCommitted) throw new IllegalStateException("commit already called");//...mCommitted = true;if (mAddToBackStack) {mIndex = mManager.allocBackStackIndex(this);} else {mIndex = -1;}mManager.enqueueAction(this, allowStateLoss);return mIndex;}//mManager.enqueueAction(this, allowStateLoss);//注意:allowStateLoss 标记public void enqueueAction(OpGenerator action, boolean allowStateLoss) {if (!allowStateLoss) {//allowStateLoss == falsecheckStateLoss();}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) {mPendingActions = new ArrayList<>();}mPendingActions.add(action);scheduleCommit();}}private void checkStateLoss() {if (isStateSaved()) {//如果宿主处于执行过onSaveInstanceState或者宿主处于stop状态 抛出如下异常throw new IllegalStateException("Can not perform this action after onSaveInstanceState");}if (mNoTransactionsBecause != null) {throw new IllegalStateException("Can not perform this action inside of " + mNoTransactionsBecause);}}//checkStateLoss调用到如下方法//这个方法就是判断 宿主是否执行过onSaveInstanceState或者宿主处于stop状态@Overridepublic boolean isStateSaved() {return mStateSaved || mStopped;}
FragmentTrancation 4中提交方式
commit(): 如果在宿主执行了onSaveInstanceState之后再执行该操作,会抛出异常,属于异步事务(注意异步事务不是在子线程中执行,而是发送一条消息到消息队列中,当轮询到该消息才会执行)。commitAllowingStateLoss():如果在宿主中执行了onSaveInstanceState之后再执行该操作,不会检查宿主的状态,不会抛出异常,该操作不会被Activity记录,恢复时也就没办法恢复这些提交操作,所以该操作使用不重要的事务(异步事务)commitNow():会立刻执行当前提交的transaction事务。属于同步事务。commitNowAllowingStateLoss() - 推荐使用 :具备以上两者的特性,即同步执行,也不会检查宿主的状态,有可能该操作不会被正确恢复。
异步事务(commit和commitAllowingStateLoss)提交最终会执行该方法:通过Handler发送到消息队列中
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);}}}/*** 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;}
同步事务(commitNow和commitNowAllowingStateLoss)提交,则会执行如下方法:
public void execSingleAction(OpGenerator action, boolean allowStateLoss) {if (allowStateLoss && (mHost == null || mDestroyed)) {// This FragmentManager isn't attached, so drop the entire transaction.return;}ensureExecReady(allowStateLoss);if (action.generateOps(mTmpRecords, mTmpIsPop)) {mExecutingActions = true;try {//移除事务的冗余操作以及执行事务removeRedundantOperationsAndExecute(mTmpRecords, mTmpIsPop);} finally {cleanupExec();}}doPendingDeferredStart();burpActive();}
removeRedundantOperationsAndExecute 是去掉事务的冗余操作如下代码.下面的这段add replace remove就是冗余操作,最终add-firstFragment.
.add(secondFragment)
.replace(threadFragment)
.remove(secondFragment)
.remove(threadFragment)
supportFragmentManager.beginTransaction().add(secondFragment).replace(threadFragment).remove(secondFragment).remove(threadFragment).add(firstFragment)
removeRedundantOperationsAndExecute 去掉事务后执行剩余的事务操作
private void removeRedundantOperationsAndExecute(ArrayList<BackStackRecord> records,ArrayList<Boolean> isRecordPop) {if (records == null || records.isEmpty()) {return;}if (isRecordPop == null || records.size() != isRecordPop.size()) {throw new IllegalStateException("Internal error with the back stack records");}// Force start of any postponed transactions that interact with scheduled transactions:executePostponedTransaction(records, isRecordPop);//依次执行事务操作final int numRecords = records.size();int startIndex = 0;for (int recordNum = 0; recordNum < numRecords; recordNum++) {final boolean canReorder = records.get(recordNum).mReorderingAllowed;if (!canReorder) {// execute all previous transactionsif (startIndex != recordNum) {executeOpsTogether(records, isRecordPop, startIndex, recordNum);}// execute all pop operations that don't allow reordering together or// one add operationint reorderingEnd = recordNum + 1;if (isRecordPop.get(recordNum)) {while (reorderingEnd < numRecords&& isRecordPop.get(reorderingEnd)&& !records.get(reorderingEnd).mReorderingAllowed) {reorderingEnd++;}}executeOpsTogether(records, isRecordPop, recordNum, reorderingEnd);startIndex = reorderingEnd;recordNum = reorderingEnd - 1;}}if (startIndex != numRecords) {executeOpsTogether(records, isRecordPop, startIndex, numRecords);}}
