image.png

FragmentManager

如下代码:通过supportFragmentManager和Activity进行关联起来

  1. supportFragmentManager.beginTransaction()
  2. .add()
  3. .replace()
  4. .remove()
  5. .remove()
  6. .add()
  7. .addToBackStack()
  8. .commit()

supportFramgentManager 后由谁提供的呢?从源码中可以看出是由FragmentController提供的,FragmentController是在FragmentActivity创建的时候初始化的。

  1. final FragmentController mFragments = FragmentController.createController(new HostCallbacks());
  2. public FragmentManager getSupportFragmentManager() {
  3. return mFragments.getSupportFragmentManager();
  4. }

我们再看一下FragmentActivity的生命周期方法:如下代码都调用了mFragments的dispatch方法,也就是说Fragment的生命周期管理委托给了FragmentController

  1. @Override
  2. protected void onStart() {
  3. super.onStart();
  4. ....
  5. mFragments.dispatchStart();
  6. }
  7. @Override
  8. protected void onStop() {
  9. super.onStop();
  10. .....
  11. mFragments.dispatchStop();
  12. }
  13. protected void onResumeFragments() {
  14. mFragments.dispatchResume();
  15. }

再来看FragmentController的代码,如下可以看到FragmentController中的代码具体是FragmentHostCallback来实现的

  1. public class FragmentController {
  2. private final FragmentHostCallback<?> mHost;
  3. public static FragmentController createController(FragmentHostCallback<?> callbacks) {
  4. return new FragmentController(callbacks);
  5. }
  6. private FragmentController(FragmentHostCallback<?> callbacks) {
  7. mHost = callbacks;
  8. }
  9. public FragmentManager getSupportFragmentManager() {
  10. return mHost.getFragmentManagerImpl();
  11. }
  12. ....
  13. }

在进入FragmentHostCallback 中创建了FragmentManager,注意Fragments may be hosted by any object 这句话,fragment可以由任何对象托管。也就是说fragment可以应用在任何地方不一定在Activity中。

  1. /**
  2. * Integration points with the Fragment host.
  3. * <p>
  4. * Fragments may be hosted by any object; such as an {@link Activity}. In order to
  5. * host fragments, implement {@link FragmentHostCallback}, overriding the methods
  6. * applicable to the host.
  7. */
  8. public abstract class FragmentHostCallback<E> extends FragmentContainer {
  9. @Nullable private final Activity mActivity;
  10. @NonNull private final Context mContext;
  11. @NonNull private final Handler mHandler;
  12. private final int mWindowAnimations;
  13. final FragmentManagerImpl mFragmentManager = new FragmentManagerImpl();
  14. }

FragmentActivity类中,实现了FragmentHostCallback抽象类:所以我们可以在Activity中管理fragment

  1. class HostCallbacks extends FragmentHostCallback<FragmentActivity> {
  2. public HostCallbacks() {
  3. super(FragmentActivity.this /*fragmentActivity*/);
  4. }
  5. @Override
  6. public void onDump(String prefix, FileDescriptor fd, PrintWriter writer, String[] args) {
  7. FragmentActivity.this.dump(prefix, fd, writer, args);
  8. }
  9. @Override
  10. public boolean onShouldSaveFragmentState(Fragment fragment) {
  11. return !isFinishing();
  12. }
  13. }

FragmentTransaction

FragmentTransaction 对fragment进行事务操作,所谓事务就是一次性进行多个操作。

如下代码进行了多个操作:add replace remove等操作

  1. supportFragmentManager.beginTransaction()
  2. .add()
  3. .replace()
  4. .remove()
  5. .remove()
  6. .add()
  7. .addToBackStack()
  8. .commit()

在FragmentManager中的方法

  1. @Override
  2. public FragmentTransaction beginTransaction() {
  3. return new BackStackRecord(this);
  4. }

调用了BackStackRecord 继承了FragmentTransaction,在操作fragment回退栈的时候能够逆向执行事务,从而实现fragment的出栈操作。

  1. /**
  2. * Entry of an operation on the fragment back stack.
  3. */
  4. final class BackStackRecord extends FragmentTransaction implements
  5. FragmentManager.BackStackEntry, FragmentManagerImpl.OpGenerator {
  6. ......
  7. }

事务操作就是在BackStackRecord中执行的,例如add操作,将fragment包装到Op包装类中,然后添加到list集合中,在提交事务的时候进行处理

  1. //add 操作标记 OP_ADD
  2. @Override
  3. public FragmentTransaction add(Fragment fragment, @Nullable String tag) {
  4. doAddOp(0, fragment, tag, OP_ADD);
  5. return this;
  6. }
  7. //replace操作 标记OP_REPLACE 添加到集合汇总
  8. @Override
  9. public FragmentTransaction replace(int containerViewId, Fragment fragment,
  10. @Nullable String tag) {
  11. if (containerViewId == 0) {
  12. throw new IllegalArgumentException("Must use non-zero containerViewId");
  13. }
  14. doAddOp(containerViewId, fragment, tag, OP_REPLACE);
  15. return this;
  16. }
  17. //remove 操作 标记OP_REMOVE 添加到集合中
  18. @Override
  19. public FragmentTransaction remove(Fragment fragment) {
  20. addOp(new Op(OP_REMOVE, fragment));
  21. return this;
  22. }
  23. ArrayList<Op> mOps = new ArrayList<>();
  24. //最终都调用了addOp方法
  25. void addOp(Op op) {
  26. mOps.add(op);
  27. op.enterAnim = mEnterAnim;
  28. op.exitAnim = mExitAnim;
  29. op.popEnterAnim = mPopEnterAnim;
  30. op.popExitAnim = mPopExitAnim;
  31. }

下面来看一下,事务提交commit操作如何处理的:

  1. @Override
  2. public int commit() {
  3. return commitInternal(false);
  4. }
  5. @Override
  6. public int commitAllowingStateLoss() {
  7. return commitInternal(true);
  8. }
  9. int commitInternal(boolean allowStateLoss) {
  10. //如果mCommitted == true 抛出异常,对于一个事物提交最多只能调用一次
  11. if (mCommitted) throw new IllegalStateException("commit already called");
  12. //...
  13. mCommitted = true;
  14. if (mAddToBackStack) {
  15. mIndex = mManager.allocBackStackIndex(this);
  16. } else {
  17. mIndex = -1;
  18. }
  19. mManager.enqueueAction(this, allowStateLoss);
  20. return mIndex;
  21. }
  22. //mManager.enqueueAction(this, allowStateLoss);
  23. //注意:allowStateLoss 标记
  24. public void enqueueAction(OpGenerator action, boolean allowStateLoss) {
  25. if (!allowStateLoss) {//allowStateLoss == false
  26. checkStateLoss();
  27. }
  28. synchronized (this) {
  29. if (mDestroyed || mHost == null) {
  30. if (allowStateLoss) {
  31. // This FragmentManager isn't attached, so drop the entire transaction.
  32. return;
  33. }
  34. throw new IllegalStateException("Activity has been destroyed");
  35. }
  36. if (mPendingActions == null) {
  37. mPendingActions = new ArrayList<>();
  38. }
  39. mPendingActions.add(action);
  40. scheduleCommit();
  41. }
  42. }
  43. private void checkStateLoss() {
  44. if (isStateSaved()) {
  45. //如果宿主处于执行过onSaveInstanceState或者宿主处于stop状态 抛出如下异常
  46. throw new IllegalStateException(
  47. "Can not perform this action after onSaveInstanceState");
  48. }
  49. if (mNoTransactionsBecause != null) {
  50. throw new IllegalStateException(
  51. "Can not perform this action inside of " + mNoTransactionsBecause);
  52. }
  53. }
  54. //checkStateLoss调用到如下方法
  55. //这个方法就是判断 宿主是否执行过onSaveInstanceState或者宿主处于stop状态
  56. @Override
  57. public boolean isStateSaved() {
  58. return mStateSaved || mStopped;
  59. }

FragmentTrancation 4中提交方式

  • commit(): 如果在宿主执行了onSaveInstanceState之后再执行该操作,会抛出异常,属于异步事务(注意异步事务不是在子线程中执行,而是发送一条消息到消息队列中,当轮询到该消息才会执行)。
  • commitAllowingStateLoss():如果在宿主中执行了onSaveInstanceState之后再执行该操作,不会检查宿主的状态,不会抛出异常,该操作不会被Activity记录,恢复时也就没办法恢复这些提交操作,所以该操作使用不重要的事务(异步事务)
  • commitNow():会立刻执行当前提交的transaction事务。属于同步事务。
  • commitNowAllowingStateLoss() - 推荐使用 :具备以上两者的特性,即同步执行,也不会检查宿主的状态,有可能该操作不会被正确恢复。

异步事务(commitcommitAllowingStateLoss)提交最终会执行该方法:通过Handler发送到消息队列中

  1. void scheduleCommit() {
  2. synchronized (this) {
  3. boolean postponeReady =
  4. mPostponedTransactions != null && !mPostponedTransactions.isEmpty();
  5. boolean pendingReady = mPendingActions != null && mPendingActions.size() == 1;
  6. if (postponeReady || pendingReady) {
  7. mHost.getHandler().removeCallbacks(mExecCommit);
  8. mHost.getHandler().post(mExecCommit);
  9. }
  10. }
  11. }
  12. /**
  13. * Only call from main thread!
  14. */
  15. public boolean execPendingActions() {
  16. ensureExecReady(true);
  17. boolean didSomething = false;
  18. while (generateOpsForPendingActions(mTmpRecords, mTmpIsPop)) {
  19. mExecutingActions = true;
  20. try {
  21. //去掉事务的冗余操作以及执行事务
  22. removeRedundantOperationsAndExecute(mTmpRecords, mTmpIsPop);
  23. } finally {
  24. cleanupExec();
  25. }
  26. didSomething = true;
  27. }
  28. doPendingDeferredStart();
  29. burpActive();
  30. return didSomething;
  31. }

同步事务(commitNowcommitNowAllowingStateLoss)提交,则会执行如下方法:

  1. public void execSingleAction(OpGenerator action, boolean allowStateLoss) {
  2. if (allowStateLoss && (mHost == null || mDestroyed)) {
  3. // This FragmentManager isn't attached, so drop the entire transaction.
  4. return;
  5. }
  6. ensureExecReady(allowStateLoss);
  7. if (action.generateOps(mTmpRecords, mTmpIsPop)) {
  8. mExecutingActions = true;
  9. try {
  10. //移除事务的冗余操作以及执行事务
  11. removeRedundantOperationsAndExecute(mTmpRecords, mTmpIsPop);
  12. } finally {
  13. cleanupExec();
  14. }
  15. }
  16. doPendingDeferredStart();
  17. burpActive();
  18. }

removeRedundantOperationsAndExecute 是去掉事务的冗余操作如下代码.下面的这段add replace remove就是冗余操作,最终add-firstFragment.
.add(secondFragment)
.replace(threadFragment)
.remove(secondFragment)
.remove(threadFragment)

  1. supportFragmentManager.beginTransaction()
  2. .add(secondFragment)
  3. .replace(threadFragment)
  4. .remove(secondFragment)
  5. .remove(threadFragment)
  6. .add(firstFragment)

removeRedundantOperationsAndExecute 去掉事务后执行剩余的事务操作

  1. private void removeRedundantOperationsAndExecute(ArrayList<BackStackRecord> records,
  2. ArrayList<Boolean> isRecordPop) {
  3. if (records == null || records.isEmpty()) {
  4. return;
  5. }
  6. if (isRecordPop == null || records.size() != isRecordPop.size()) {
  7. throw new IllegalStateException("Internal error with the back stack records");
  8. }
  9. // Force start of any postponed transactions that interact with scheduled transactions:
  10. executePostponedTransaction(records, isRecordPop);
  11. //依次执行事务操作
  12. final int numRecords = records.size();
  13. int startIndex = 0;
  14. for (int recordNum = 0; recordNum < numRecords; recordNum++) {
  15. final boolean canReorder = records.get(recordNum).mReorderingAllowed;
  16. if (!canReorder) {
  17. // execute all previous transactions
  18. if (startIndex != recordNum) {
  19. executeOpsTogether(records, isRecordPop, startIndex, recordNum);
  20. }
  21. // execute all pop operations that don't allow reordering together or
  22. // one add operation
  23. int reorderingEnd = recordNum + 1;
  24. if (isRecordPop.get(recordNum)) {
  25. while (reorderingEnd < numRecords
  26. && isRecordPop.get(reorderingEnd)
  27. && !records.get(reorderingEnd).mReorderingAllowed) {
  28. reorderingEnd++;
  29. }
  30. }
  31. executeOpsTogether(records, isRecordPop, recordNum, reorderingEnd);
  32. startIndex = reorderingEnd;
  33. recordNum = reorderingEnd - 1;
  34. }
  35. }
  36. if (startIndex != numRecords) {
  37. executeOpsTogether(records, isRecordPop, startIndex, numRecords);
  38. }
  39. }