美文网首页
Android-Fragment事务管理原理分析

Android-Fragment事务管理原理分析

作者: zzq_nene | 来源:发表于2020-12-11 15:03 被阅读0次

一、Fragment事务提交的部分操作

1.相关源码概念

FragmetActivity的getSupportFragmentManager()内部是通过FragmentController.getSupportFragmentManager,而FragmentController的内部是获取的HostCallbacks对象中的FragmentManager对象,这个对象在最新版本的Androidx源码中,虽然是FragmentManagerImpl对象,但是FragmentManagerImpl其实是一个空子类。
通过FragmentManager.beginTransaction()获取FragmentTransaction对象,而FragmentManager.beginTransaction()中的方法实现如下:

    public FragmentTransaction beginTransaction() {
        return new BackStackRecord(this);
    }

FragmentTransaction.add
FragmentTransaction.remove
FragmentTransaction.replace
FragmentTransaction.hide
FragmentTransaction.show
FragmentTransaction.setPrimaryNavigationFragment
FragmentTransaction.addToBackStack
FragmentTransaction.commit
FragmentTransaction的实现类只有一个BackStackRecord
其实这些所有的add、replace等,最终都是将Fragment的状态变成了ADD,然后最终在执行的时候,都是通过调用FragmentManager.moveToState方法,createView,一直开始执行生命周期,而在FragmentManager.moveToState方法中,每个生命周期执行完成之后,都会继续调用moveToState转成下一个步骤的生命周期状态。
使用事务,是为了保证连续的操作是原子性的。
调用hide和show的时候,其实并不会去走生命周期。

2.FragmentActivity#getSupportFragmentManager()

该源码逻辑在在上面已经说了,这里就贴下源码:

    // FragmentActivity.java
    public FragmentManager getSupportFragmentManager() {
        // 这里的mFragments其实就是FragmentController对象
        return mFragments.getSupportFragmentManager();
    }
    // FragmentController.java
    public FragmentManager getSupportFragmentManager() {
        // 获取HostCallbacks对象中创建的FragmentManager对象
        return mHost.mFragmentManager;
    }
// FragmentHostCallback.java   这是HostCallbacks的父类,泛型是传入的FragmentActivity
final FragmentManager mFragmentManager = new FragmentManagerImpl();

3.FragmentManager#beginTransaction

    // 获取事务类,BackStackRecord其实就是FragmentTransaction的子类实现
    public FragmentTransaction beginTransaction() {
        return new BackStackRecord(this);
    }
// 从BackStackRecord的源码可以看出,BackStackRecord实现了FragmentTransaction抽象类
// 还实现了FragmentManager.OpGenerator接口,所以在这个流程中,保存事务的时候,可能会以FragmentManager.OpGenerator对象
// 也可能会以BackStackRecord保存,这是同一个。
final class BackStackRecord extends FragmentTransaction implements
        FragmentManager.BackStackEntry, FragmentManager.OpGenerator {

4.FragmentTransaction#add

(1)直接传入Fragment的Class对象,在内部创建Fragment
    public final FragmentTransaction add(@NonNull Class<? extends Fragment> fragmentClass,
            @Nullable Bundle args, @Nullable String tag)  {
        return add(createFragment(fragmentClass, args), tag);
    }
    public FragmentTransaction add(@NonNull Fragment fragment, @Nullable String tag)  {
        // 调用add方法,设置Op的mCmd指令为OP_ADD
        doAddOp(0, fragment, tag, OP_ADD);
        return this;
    }
(2)传入布局控件id和Fragment对象
    public final FragmentTransaction add(@IdRes int containerViewId,
            @NonNull Class<? extends Fragment> fragmentClass, @Nullable Bundle args)  {
        return add(containerViewId, createFragment(fragmentClass, args));
    }
    public FragmentTransaction add(@IdRes int containerViewId, @NonNull Fragment fragment) {
        doAddOp(containerViewId, fragment, null, OP_ADD);
        return this;
    }

5.FragmentTransaction#doAddOp

如果传入的是Fragment的Class对象,这doAddOp操作的第一个参数直接传0,如果是传入具体的containerViewId,则使用具体的containerViewId

    // 这步的主要操作就是设置tag和containerId
    void doAddOp(int containerViewId, Fragment fragment, @Nullable String tag, int opcmd) {
        final Class<?> fragmentClass = fragment.getClass();
        final int modifiers = fragmentClass.getModifiers();
        if (fragmentClass.isAnonymousClass() || !Modifier.isPublic(modifiers)
                || (fragmentClass.isMemberClass() && !Modifier.isStatic(modifiers))) {
            throw new IllegalStateException("Fragment " + fragmentClass.getCanonicalName()
                    + " must be a public static class to be  properly recreated from"
                    + " instance state.");
        }

        if (tag != null) {
            if (fragment.mTag != null && !tag.equals(fragment.mTag)) {
                throw new IllegalStateException("Can't change tag of fragment "
                        + fragment + ": was " + fragment.mTag
                        + " now " + tag);
            }
            fragment.mTag = tag;
        }
        // 判断布局id是否为0,如果不为0,设置给fragment对象的mContainerId值
        // 这是用于在fragment对象进行createView的时候使用
        if (containerViewId != 0) {
            if (containerViewId == View.NO_ID) {
                throw new IllegalArgumentException("Can't add fragment "
                        + fragment + " with tag " + tag + " to container view with no id");
            }
            if (fragment.mFragmentId != 0 && fragment.mFragmentId != containerViewId) {
                throw new IllegalStateException("Can't change container ID of fragment "
                        + fragment + ": was " + fragment.mFragmentId
                        + " now " + containerViewId);
            }
            // 设置宿主ID为布局ID
            fragment.mContainerId = fragment.mFragmentId = containerViewId;
        }
        // 将fragment和opcmd指令封装成一个Op对象,Op对象其是对于Fragment的操作对象,封装fragment的相关操作信息
        addOp(new Op(opcmd, fragment));
    }

6.FragmentTransaction#addOp

    void addOp(Op op) {
        // 将每个Fragment相关的操作对象添加到ArrayList集合中,用于提交的时候使用
        mOps.add(op);
        op.mEnterAnim = mEnterAnim;
        op.mExitAnim = mExitAnim;
        op.mPopEnterAnim = mPopEnterAnim;
        op.mPopExitAnim = mPopExitAnim;
    }

7.BackStackRecord#commit

BackStackRecord的提交有四个方法,这里做统一分析:然后最后就分析commit()的后续流程,因为大体相同,主要就是异步和同步提交不同。

    // commit() 在主线程中异步执行,其实也是 Handler 抛出任务,等待主线程调度执行。
    // commit需要在Activity保存状态之前提交,否则会报错。
    // 因为Activity出现异常需要恢复状态,在保存状态之后的commit会丢失
    @Override
    public int commit() {
        return commitInternal(false);
    }

    // commitAllowingStateLoss() 也是异步执行,但它的不同之处在于,允许在 Activity 
    // 保存状态之后调用,也就是说它遇到状态丢失不会报错。
    @Override
    public int commitAllowingStateLoss() {
        return commitInternal(true);
    }

    // 这是同步执行的。立即提交事务。与FragmentManager.executePendingTransactions
    // 类似,但是推荐使用commitNow。因为executePendingTransactions会一次性
    // 执行所有待执行的事务,可能会有副作用。而且executePendingTransactions方法提交
    // 的事务可能不会被添加到FragmentManager的回退栈中,因为这样直接提交可能会影响
    // 其他异步执行任务在栈中的顺序
    // commitNow的提交也不能在状态保存之后进行
    // TODO:这两个方法在调用的时候,是禁止使用回退栈功能的
    @Override
    public void commitNow() {
        disallowAddToBackStack();
        mManager.execSingleAction(this, false);
    }

    @Override
    public void commitNowAllowingStateLoss() {
        disallowAddToBackStack();
        mManager.execSingleAction(this, true);
    }

8.BackStackRecord#commitInternal

    int commitInternal(boolean allowStateLoss) {
        if (mCommitted) throw new IllegalStateException("commit already called");
        if (FragmentManager.isLoggingEnabled(Log.VERBOSE)) {
            Log.v(TAG, "Commit: " + this);
            LogWriter logw = new LogWriter(TAG);
            PrintWriter pw = new PrintWriter(logw);
            dump("  ", pw);
            pw.close();
        }
        mCommitted = true;
        // 这里的index,其实是记录当前事务可以放置的位置的
        // 如果是fragment-1.1.0版本,是采用两个集合的方式,一个集合保存BackStackRecord
        // 另一个集合保存因为回退之后,空出来的位置的索引
        // 但是在fragment-1.2.1版本中,采用的是AtomicInteger,比较并交换的做法
        if (mAddToBackStack) {
            // 这里是回退栈可用的情况,则需要计算一个index
            // 这里因为Androidx版本的区别,实现也不同。
            // 这里的代码是fragment-1.2.1版本的库
            mIndex = mManager.allocBackStackIndex();
            // 如果是fragment-1.1.0的库,则与这里实现不同,如下所示
            // mIndex = mManager.allocBackStackIndex(this);
        } else {
            mIndex = -1;
        }
        mManager.enqueueAction(this, allowStateLoss);
        return mIndex;
    }

9.FragmentManager#allocBackStackIndex()

这是fragment-1.2.1-androidx的源码
这里采用AtomicInteger,是为了保证在异步提交事务处理的时候,保证index的一个原子性

    int allocBackStackIndex() {
        return mBackStackIndex.getAndIncrement();
    }

对比fragment-1.1.0-androidx的源码
在这里,是采用两个ArrayList数组的方式,一个用来保存当前提交的事务,而另一个是用来保存当前事务集合中的可用位置,这样说可能比较抽象,看源码分析。

    public int allocBackStackIndex(BackStackRecord bse) {
        synchronized (this) {
            // 第一次提交的时候,mAvailBackStackIndices是为null或者size==0的
            // 所以执行if条件
            if (mAvailBackStackIndices == null || mAvailBackStackIndices.size() <= 0) {
                // 初始化mBackStackIndices保存事务
                if (mBackStackIndices == null) {
                    mBackStackIndices = new ArrayList<BackStackRecord>();
                }
                // 找到当前添加的事务的索引位置,在这里,因为是添加到了mBackStackIndices的末尾
                // 所以添加的集合的索引位置其实就是添加之前的集合的长度
                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 setBackStackIndex(int index, BackStackRecord bse) {
        synchronized (this) {
            if (mBackStackIndices == null) {
                mBackStackIndices = new ArrayList<BackStackRecord>();
            }
            int N = mBackStackIndices.size();
            // 如果index小于mBackStackIndices的长度,说明mBackStackIndices中有取出添加到回退栈的事务
            // 那么基于复用原则,继续复用之前取出的位置存放当前添加的事务
            if (index < N) {
                if (DEBUG) Log.v(TAG, "Setting back stack index " + index + " to " + bse);
                mBackStackIndices.set(index, bse);
            } else {
                // 如果存储集合的长度是小于要添加的位置,则向集合的末尾添加事务
                while (N < index) {
                    mBackStackIndices.add(null);
                    if (mAvailBackStackIndices == null) {
                        mAvailBackStackIndices = new ArrayList<Integer>();
                    }
                    if (DEBUG) Log.v(TAG, "Adding available back stack index " + N);
                    mAvailBackStackIndices.add(N);
                    N++;
                }
                if (DEBUG) Log.v(TAG, "Adding back stack index " + index + " with " + bse);
                // 这里是index==N的条件
                mBackStackIndices.add(bse);
            }
        }
    }
    // 释放存储事务集合中的事务
    public void freeBackStackIndex(int index) {
        synchronized (this) {
            // 在释放mBackStackIndices中的事务的时候,并不是单纯的将集合的index位置释放,然后重新排序集合
            // 而是采用一个null来填充,用于下一次的复用
            mBackStackIndices.set(index, null);
            if (mAvailBackStackIndices == null) {
                mAvailBackStackIndices = new ArrayList<Integer>();
            }
            if (DEBUG) Log.v(TAG, "Freeing back stack index " + index);
            // 这里存储的其实就是之前被释放的事务的位置,这样的做法,其实就是方便
            // 下一次添加事务的时候,能够精准的找到mBackStackIndices中对应的位置存放事务
            mAvailBackStackIndices.add(index);
        }
    }

10.FragmentManager#enqueueAction

    void enqueueAction(@NonNull OpGenerator action, boolean allowStateLoss) {
        // 判断是否需要检查状态,即是否允许在保存状态之后提交事务进行丢弃
        // 如果allowStateLoss是false,则需要检查当前事务提交的时候是否已经进行onSaveInstanceState操作
        if (!allowStateLoss) {
            if (mHost == null) {
                if (mDestroyed) {
                    throw new IllegalStateException("FragmentManager has been destroyed");
                } else {
                    throw new IllegalStateException("FragmentManager has not been attached to a "
                            + "host.");
                }
            }
            checkStateLoss();
        }
        // mPendingActions中添加的是正在等待处理的事务
        synchronized (mPendingActions) {
            // 如果HostCallbacks对象为null,判断allowStateLoss是否为true
            // 如果为true,则直接return,否则抛出异常,提示activity已经被销毁
            if (mHost == null) {
                if (allowStateLoss) {
                    // This FragmentManager isn't attached, so drop the entire transaction.
                    return;
                }
                throw new IllegalStateException("Activity has been destroyed");
            }
            mPendingActions.add(action);
            // 异步执行提交操作
            scheduleCommit();
        }
    }

11.FragmentManager#scheduleCommit

    // 执行异步任务
    void scheduleCommit() {
        synchronized (mPendingActions) {
            boolean postponeReady =
                    mPostponedTransactions != null && !mPostponedTransactions.isEmpty();
            boolean pendingReady = mPendingActions.size() == 1;
            if (postponeReady || pendingReady) {
                // 这里就是采用之前添加到HostCallbacks对象中的Handler来执行异步任务操作
                // 首先删除上一次执行的提交的任务
                mHost.getHandler().removeCallbacks(mExecCommit);
                // 然后再执行当前新的提交请求
                // mExecCommit其实是一个Runnable对象
                mHost.getHandler().post(mExecCommit);
                updateOnBackPressedCallbackEnabled();
            }
        }
    }

12.FragmentManager#mExecCommit对象

    private Runnable mExecCommit = new Runnable() {
        @Override
        public void run() {
            // 由HostCallbacks中的Handler进行执行该任务
            execPendingActions(true);
        }
    };

13.FragmentManager#execPendingActions

    // 只能从主线程调用该方法
    boolean execPendingActions(boolean allowStateLoss) {
    // 确保执行是处于就绪阶段,即没有正在执行的事务,也HostCallbacks也不为null
    // 且是在主线程中,并且初始化mTmpRecords和mTmpIsPop
    // 这里就是针对execPendingActions的方法执行的线程检查的操作
        ensureExecReady(allowStateLoss);

        boolean didSomething = false;
    // 这里的操作,其实就是在mPendingActions中取出BackStackRecord
    // mPendingActions中存的是OpGenerator,而BackStackRecord实现了该接口
    // mTmpRecords存的就是BackStackRecord
    // 所以这里的目的就算将待执行的事务添加到mTmpRecords
    // 而在mTmpIsPop对应位置会根据是否允许添加到回退栈而设置true还是false
    // 这里如果mPendingActions为null,则直接返回false
        while (generateOpsForPendingActions(mTmpRecords, mTmpIsPop)) {
            mExecutingActions = true;
            try {
            // 这里是删除冗余操作,并且执行事务
            // 所谓的冗余操作:比如一次事务提交,对一个Fragment进行了add
            // 又进行了remove,然后又进行了add,这样只有最后一次add有效
            // 在这里会修改事务的状态,比如将replace的事务变成ADD的
            // 最终就会执行处理事务
            // 如果没有回退栈相关,则是调用事务BackStackRecord.executeOps方法
                removeRedundantOperationsAndExecute(mTmpRecords, mTmpIsPop);
            } finally {
                cleanupExec();
            }
            didSomething = true;
        }

        updateOnBackPressedCallbackEnabled();
    // 执行延迟启动的Fragment,修改其状态
        doPendingDeferredStart();
    // 这里为了防止列表错误,将mActive的值置为null
    // 而不是在Fragment变为非活动状态的时候将其删除。
    // 但是在执行事务结束时会清理列表
        mFragmentStore.burpActive();

        return didSomething;
    }

14.FragmentManager#removeRedundantOperationsAndExecute

这里的主要目的就是为了移除事务提交过程中,事务列表中冗余的BackStackRecord对象。

    private void removeRedundantOperationsAndExecute(@NonNull ArrayList<BackStackRecord> records,
            @NonNull ArrayList<Boolean> isRecordPop) {
        if (records.isEmpty()) {
            return;
        }

        if (records.size() != isRecordPop.size()) {
            throw new IllegalStateException("Internal error with the back stack records");
        }

      // 针对与计划处理的事务有交互的任何延迟的事务,进行强制执行
      // 不过这些事务是过去延迟处理,但是当前已经准备好的事务
        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) {
                // 执行先前的所有事务
                if (startIndex != recordNum) {
                    executeOpsTogether(records, isRecordPop, startIndex, recordNum);
                }
                // 执行所有不允许重新排序的出栈操作或者事务的添加操作
                int 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);
        }
    }

15.FragmentManager#executeOpsTogether

    private void executeOpsTogether(@NonNull ArrayList<BackStackRecord> records,
            @NonNull ArrayList<Boolean> isRecordPop, int startIndex, int endIndex) {
        final boolean allowReordering = records.get(startIndex).mReorderingAllowed;
        boolean addToBackStack = false;
        // 添加Fragment到集合中,该集合是ADD状态的Fragment集合
        if (mTmpAddedFragments == null) {
            mTmpAddedFragments = new ArrayList<>();
        } else {
            mTmpAddedFragments.clear();
        }
        mTmpAddedFragments.addAll(mFragmentStore.getFragments());
        Fragment oldPrimaryNav = getPrimaryNavigationFragment();
        for (int recordNum = startIndex; recordNum < endIndex; recordNum++) {
            final BackStackRecord record = records.get(recordNum);
            final boolean isPop = isRecordPop.get(recordNum);
            if (!isPop) {
                // 如果是不允许出栈的,修改事务的操作状态
                // 比如将replace的操作也变成了ADD操作,这里其实就是想ADD状态集合添加Fragment
                oldPrimaryNav = record.expandOps(mTmpAddedFragments, oldPrimaryNav);
            } else {
                oldPrimaryNav = record.trackAddedFragmentsInPop(mTmpAddedFragments, oldPrimaryNav);
            }
            addToBackStack = addToBackStack || record.mAddToBackStack;
        }
        mTmpAddedFragments.clear();

        if (!allowReordering) {
            FragmentTransition.startTransitions(this, records, isRecordPop, startIndex, endIndex,
                    false, mFragmentTransitionCallback);
        }
        // 这里是具体执行对Fragment的add、replace、hide、show等操作的
        executeOps(records, isRecordPop, startIndex, endIndex);

        int postponeIndex = endIndex;
        // 判断是否允许重新排序
        if (allowReordering) {
            ArraySet<Fragment> addedFragments = new ArraySet<>();
            addAddedFragments(addedFragments);
            postponeIndex = postponePostponableTransactions(records, isRecordPop,
                    startIndex, endIndex, addedFragments);
            makeRemovedFragmentsInvisible(addedFragments);
        }

        if (postponeIndex != startIndex && allowReordering) {
            // need to run something now
            FragmentTransition.startTransitions(this, records, isRecordPop, startIndex,
                    postponeIndex, true, mFragmentTransitionCallback);
            moveToState(mCurState, true);
        }

        for (int recordNum = startIndex; recordNum < endIndex; recordNum++) {
            final BackStackRecord record = records.get(recordNum);
            final boolean isPop = isRecordPop.get(recordNum);
            if (isPop && record.mIndex >= 0) {
                record.mIndex = -1;
            }
            record.runOnCommitRunnables();
        }
        if (addToBackStack) {
            reportBackStackChanged();
        }
    }

16.BackStackRecord#expandOps

这里主要是找到旧的Fragment的导航

    Fragment expandOps(ArrayList<Fragment> added, Fragment oldPrimaryNav) {
        for (int opNum = 0; opNum < mOps.size(); opNum++) {
            final Op op = mOps.get(opNum);
            switch (op.mCmd) {
                case OP_ADD:
                case OP_ATTACH:
                    added.add(op.mFragment);
                    break;
                case OP_REMOVE:
                case OP_DETACH: {
                    added.remove(op.mFragment);
                    if (op.mFragment == oldPrimaryNav) {
                        mOps.add(opNum, new Op(OP_UNSET_PRIMARY_NAV, op.mFragment));
                        opNum++;
                        oldPrimaryNav = null;
                    }
                }
                break;
                case OP_REPLACE: {
                    // REPLACE状态,如果是已经添加的,则需要删除已经添加的,然后再一次添加新的
                    final Fragment f = op.mFragment;
                    final int containerId = f.mContainerId;
                    boolean alreadyAdded = false;
                    for (int i = added.size() - 1; i >= 0; i--) {
                        final Fragment old = added.get(i);
                        if (old.mContainerId == containerId) {
                            // 判断旧的Fragment和当前要添加的Fragment是否一致
                            if (old == f) {
                                alreadyAdded = true;
                            } else {
                                // This is duplicated from above since we only make
                                // a single pass for expanding ops. Unset any outgoing primary nav.
                                if (old == oldPrimaryNav) {
                                    mOps.add(opNum, new Op(OP_UNSET_PRIMARY_NAV, old));
                                    opNum++;
                                    oldPrimaryNav = null;
                                }
                                final Op removeOp = new Op(OP_REMOVE, old);
                                removeOp.mEnterAnim = op.mEnterAnim;
                                removeOp.mPopEnterAnim = op.mPopEnterAnim;
                                removeOp.mExitAnim = op.mExitAnim;
                                removeOp.mPopExitAnim = op.mPopExitAnim;
                                mOps.add(opNum, removeOp);
                                added.remove(old);
                                opNum++;
                            }
                        }
                    }
                    // 如果是已经添加,则先删除已经添加的,然后在加入新的
                    // 再将op.mCmd改成OP_ADD
                    if (alreadyAdded) {
                        mOps.remove(opNum);
                        opNum--;
                    } else {
                        op.mCmd = OP_ADD;
                        added.add(f);
                    }
                }
                break;
                case OP_SET_PRIMARY_NAV: {
                    // It's ok if this is null, that means we will restore to no active
                    // primary navigation fragment on a pop.
                    mOps.add(opNum, new Op(OP_UNSET_PRIMARY_NAV, oldPrimaryNav));
                    opNum++;
                    // Will be set by the OP_SET_PRIMARY_NAV we inserted before when run
                    oldPrimaryNav = op.mFragment;
                }
                break;
            }
        }
        return oldPrimaryNav;
    }

17.FragmentManager#executeOps

    private static void executeOps(@NonNull ArrayList<BackStackRecord> records,
            @NonNull ArrayList<Boolean> isRecordPop, int startIndex, int endIndex) {
        for (int i = startIndex; i < endIndex; i++) {
            final BackStackRecord record = records.get(i);
            final boolean isPop = isRecordPop.get(i);
            if (isPop) {
                record.bumpBackStackNesting(-1);
                // Only execute the add operations at the end of
                // all transactions.
                boolean moveToState = i == (endIndex - 1);
                record.executePopOps(moveToState);
            } else {
                record.bumpBackStackNesting(1);
                // 执行事务
                record.executeOps();
            }
        }
    }

18.BackStackRecord#executeOps

    void executeOps() {
        final int numOps = mOps.size();
        for (int opNum = 0; opNum < numOps; opNum++) {
            final Op op = mOps.get(opNum);
            final Fragment f = op.mFragment;
            if (f != null) {
                f.setNextTransition(mTransition);
            }
            switch (op.mCmd) {
                case OP_ADD:
                    f.setNextAnim(op.mEnterAnim);
                    mManager.setExitAnimationOrder(f, false);
                    mManager.addFragment(f);
                    break;
                case OP_REMOVE:
                    f.setNextAnim(op.mExitAnim);
                    mManager.removeFragment(f);
                    break;
                case OP_HIDE:
                    f.setNextAnim(op.mExitAnim);
                    mManager.hideFragment(f);
                    break;
                case OP_SHOW:
                    f.setNextAnim(op.mEnterAnim);
                    mManager.setExitAnimationOrder(f, false);
                    mManager.showFragment(f);
                    break;
                case OP_DETACH:
                    f.setNextAnim(op.mExitAnim);
                    mManager.detachFragment(f);
                    break;
                case OP_ATTACH:
                    f.setNextAnim(op.mEnterAnim);
                    mManager.setExitAnimationOrder(f, false);
                    mManager.attachFragment(f);
                    break;
                case OP_SET_PRIMARY_NAV:
                    mManager.setPrimaryNavigationFragment(f);
                    break;
                case OP_UNSET_PRIMARY_NAV:
                    mManager.setPrimaryNavigationFragment(null);
                    break;
                case OP_SET_MAX_LIFECYCLE:
                    mManager.setMaxLifecycle(f, op.mCurrentMaxState);
                    break;
                default:
                    throw new IllegalArgumentException("Unknown cmd: " + op.mCmd);
            }
            if (!mReorderingAllowed && op.mCmd != OP_ADD && f != null) {
                mManager.moveFragmentToExpectedState(f);
            }
        }
        if (!mReorderingAllowed) {
            // 事务提交之后,根据当前状态,执行fragment的生命周期
            mManager.moveToState(mManager.mCurState, true);
        }
    }

19.FragmentManager#addFragment/removeFragment/hideFragment/showFragment/detachFragment/attachFragment

    void addFragment(@NonNull Fragment fragment) {
        if (isLoggingEnabled(Log.VERBOSE)) Log.v(TAG, "add: " + fragment);
        makeActive(fragment);
        if (!fragment.mDetached) {
            // 向mAdded集合中添加fragment,mAdded集合是保存添加的Fragment
            // 用于在moveToState的处理添加的Fragment
            mFragmentStore.addFragment(fragment);
            fragment.mRemoving = false;
            if (fragment.mView == null) {
                // 添加之后,设置隐藏状态为false
                fragment.mHiddenChanged = false;
            }
            if (isMenuAvailable(fragment)) {
                mNeedMenuInvalidate = true;
            }
        }
    }

    void removeFragment(@NonNull Fragment fragment) {
        if (isLoggingEnabled(Log.VERBOSE)) {
            Log.v(TAG, "remove: " + fragment + " nesting=" + fragment.mBackStackNesting);
        }
        final boolean inactive = !fragment.isInBackStack();
        if (!fragment.mDetached || inactive) {
            // 从mAdded集合中删除fragment
            mFragmentStore.removeFragment(fragment);
            if (isMenuAvailable(fragment)) {
                mNeedMenuInvalidate = true;
            }
            fragment.mRemoving = true;
            setVisibleRemovingFragment(fragment);
        }
    }

    void hideFragment(@NonNull Fragment fragment) {
        if (isLoggingEnabled(Log.VERBOSE)) Log.v(TAG, "hide: " + fragment);
        if (!fragment.mHidden) {
            // 设置fragment的隐藏状态为true
            fragment.mHidden = true;
            // Toggle hidden changed so that if a fragment goes through show/hide/show
            // it doesn't go through the animation.
            fragment.mHiddenChanged = !fragment.mHiddenChanged;
            setVisibleRemovingFragment(fragment);
        }
    }

    void showFragment(@NonNull Fragment fragment) {
        if (isLoggingEnabled(Log.VERBOSE)) Log.v(TAG, "show: " + fragment);
        if (fragment.mHidden) {
            // 设置fragment的隐藏状态
            fragment.mHidden = false;
            // Toggle hidden changed so that if a fragment goes through show/hide/show
            // it doesn't go through the animation.
            fragment.mHiddenChanged = !fragment.mHiddenChanged;
        }
    }

    void detachFragment(@NonNull Fragment fragment) {
        if (isLoggingEnabled(Log.VERBOSE)) Log.v(TAG, "detach: " + fragment);
        if (!fragment.mDetached) {
            fragment.mDetached = true;
            if (fragment.mAdded) {
                // We are not already in back stack, so need to remove the fragment.
                if (isLoggingEnabled(Log.VERBOSE)) Log.v(TAG, "remove from detach: " + fragment);
                mFragmentStore.removeFragment(fragment);
                if (isMenuAvailable(fragment)) {
                    mNeedMenuInvalidate = true;
                }
                setVisibleRemovingFragment(fragment);
            }
        }
    }

    void attachFragment(@NonNull Fragment fragment) {
        if (isLoggingEnabled(Log.VERBOSE)) Log.v(TAG, "attach: " + fragment);
        if (fragment.mDetached) {
            fragment.mDetached = false;
            if (!fragment.mAdded) {
                mFragmentStore.addFragment(fragment);
                if (isLoggingEnabled(Log.VERBOSE)) Log.v(TAG, "add from attach: " + fragment);
                if (isMenuAvailable(fragment)) {
                    mNeedMenuInvalidate = true;
                }
            }
        }
    }

20.FragmentManager#moveToState

    void moveToState(int newState, boolean always) {
        if (mHost == null && newState != Fragment.INITIALIZING) {
            throw new IllegalStateException("No activity");
        }

        if (!always && newState == mCurState) {
            return;
        }

        mCurState = newState;

        // Must add them in the proper order. mActive fragments may be out of order
        for (Fragment f : mFragmentStore.getFragments()) {
            moveFragmentToExpectedState(f);
        }

        // Now iterate through all active fragments. These will include those that are removed
        // and detached.
        for (Fragment f : mFragmentStore.getActiveFragments()) {
            if (f != null && !f.mIsNewlyAdded) {
                moveFragmentToExpectedState(f);
            }
        }

        startPendingDeferredFragments();

        if (mNeedMenuInvalidate && mHost != null && mCurState == Fragment.RESUMED) {
            mHost.onSupportInvalidateOptionsMenu();
            mNeedMenuInvalidate = false;
        }
    }

21.FragmentManager#moveFragmentToExpectedState

    void moveFragmentToExpectedState(@NonNull Fragment f) {
        if (!mFragmentStore.containsActiveFragment(f.mWho)) {
            if (isLoggingEnabled(Log.DEBUG)) {
                Log.d(TAG, "Ignoring moving " + f + " to state " + mCurState
                        + "since it is not added to " + this);
            }
            return;
        }
        // 在CREATED状态的时候会创建View,保存在Fragment
        moveToState(f);

        if (f.mView != null) {
            // Move the view if it is out of order
            Fragment underFragment = mFragmentStore.findFragmentUnder(f);
            if (underFragment != null) {
                final View underView = underFragment.mView;
                // make sure this fragment is in the right order.
                final ViewGroup container = f.mContainer;
                int underIndex = container.indexOfChild(underView);
                int viewIndex = container.indexOfChild(f.mView);
                if (viewIndex < underIndex) {
                    container.removeViewAt(viewIndex);
                    container.addView(f.mView, underIndex);
                }
            }
            if (f.mIsNewlyAdded && f.mContainer != null) {
                // Make it visible and run the animations
                if (f.mPostponedAlpha > 0f) {
                    f.mView.setAlpha(f.mPostponedAlpha);
                }
                f.mPostponedAlpha = 0f;
                f.mIsNewlyAdded = false;
                // run animations:
                FragmentAnim.AnimationOrAnimator anim = FragmentAnim.loadAnimation(
                        mHost.getContext(), mContainer, f, true);
                if (anim != null) {
                    if (anim.animation != null) {
                        f.mView.startAnimation(anim.animation);
                    } else {
                        anim.animator.setTarget(f.mView);
                        anim.animator.start();
                    }
                }
            }
        }
        // 是否隐藏的状态,如果是true,这执行完成隐藏显示Fragment的操作
        if (f.mHiddenChanged) {
            completeShowHideFragment(f);
        }
    }

相关文章

  • Android-Fragment事务管理原理分析

    一、Fragment事务提交的部分操作 1.相关源码概念 FragmetActivity的getSupportFr...

  • spring事务管理

    1. 事务管理的基本原理 spring事务管理实际上数据库对事务的支持,在java中使用的是JDBC的事务管理机制...

  • Android-Fragment简要分析

    注意:文章对Fragment源码的分析基于support v4的Fragment包,版本号为25.3.1 Frag...

  • Mybatis原理--事务管理

    本文将会介绍Mybatis的事务管理机制的原理,首先介绍下事务管理的特质、在Mybatis中是如何创建事务、事务有...

  • 7.5 Spring事务控制

    在Spring学习的书中,AOP最常见的应用场景就是事务管理了。基于AOP的事务管理是声明式事务,原理就是在方法的...

  • @Transaction必知必会

    1. Spring事务的基本原理 事务管理是应用系统开发中必不可少的一部分。Spring 为事务管理提供了丰富的功...

  • Java之Collection

    Collection接口介绍常用Set原理分析常用Queue原理分析常用List原理分析 Collection接口...

  • 动态数据源dynamic-datasource,切换失效问题

    环境: 数据库操作mybatis-plus原因:使用了spring自带的事务管理.原理:spring自带事务会创建...

  • 三、SpringBoot原理分析

    三、SpringBoot原理分析 3.1 起步依赖原理分析 3.1.1 分析spring-boot-starter...

  • SpringBoot知识 day02

    一、SpringBoot原理分析 1.1 起步依赖原理分析 1.1.1 分析spring-boot-starter...

网友评论

      本文标题:Android-Fragment事务管理原理分析

      本文链接:https://www.haomeiwen.com/subject/dhooyktx.html