美文网首页
组件之Fragment源码解析

组件之Fragment源码解析

作者: kjy_112233 | 来源:发表于2018-09-26 20:21 被阅读0次

    一、Framgnet源码解析

    (1)getSupportFragmentManager()源码

    • mHost.mFragmentManager获取的是FragmentMananger的实现类FragmentManagerImpl。
        @NonNull
        public FragmentManager getSupportFragmentManager() {
            return mFragments.getSupportFragmentManager();
        }
    
        //FragmentController.java
        @NonNull
        public FragmentManager getSupportFragmentManager() {
            return mHost.mFragmentManager;
        }
    

    (2)FragmentManagerImpl.beginTransaction()源码

    • new BackStackRecord(this)获取的是FragmentTransaction的实现类BackStackRecord(事务管理器)。
        @NonNull
        @Override
        public FragmentTransaction beginTransaction() {
            return new BackStackRecord(this);
        }
    

    (3)FragmentTransaction.add()源码

    • 在add方法中,系统只做了赋值操作,并没有对Fragment进行任何操作。
    • opcmd标记是什么类型的操作
    • 将fragment等信息追加到ArrayList列表的末尾。
        @NonNull
        public FragmentTransaction add(@NonNull Fragment fragment, @Nullable String tag)  {
            doAddOp(0, fragment, tag, OP_ADD);
            return this;
        }
    
        @NonNull
        public FragmentTransaction add(@IdRes int containerViewId, @NonNull Fragment fragment) {
            doAddOp(containerViewId, fragment, null, OP_ADD);
            return this;
        }
    
        @NonNull
        public FragmentTransaction add(@IdRes int containerViewId, @NonNull Fragment fragment, @Nullable String tag) {
            doAddOp(containerViewId, fragment, tag, OP_ADD);
            return this;
        }
    
        //BackStackRecord.java
        @Override
        void doAddOp(int containerViewId, Fragment fragment, @Nullable String tag, int opcmd) {
            super.doAddOp(containerViewId, fragment, tag, opcmd);
            fragment.mFragmentManager = mManager;
        }
    
        void doAddOp(int containerViewId, Fragment fragment, @Nullable String tag, int opcmd) {
            //code...
            addOp(new Op(opcmd, fragment));
        }
    
            Op(int cmd, Fragment fragment) {
                this.mCmd = cmd;
                this.mFragment = fragment;
                this.mOldMaxState = Lifecycle.State.RESUMED;
                this.mCurrentMaxState = Lifecycle.State.RESUMED;
            }
    
        void addOp(Op op) {
            mOps.add(op);
            op.mEnterAnim = mEnterAnim;
            op.mExitAnim = mExitAnim;
            op.mPopEnterAnim = mPopEnterAnim;
            op.mPopExitAnim = mPopExitAnim;
        }
    

    (4)BackStackRecord.commit源码

        @Override
        public int commit() {
            return commitInternal(false);
        }
    
        int commitInternal(boolean allowStateLoss) {
            //code..
            if (mAddToBackStack) {
                mIndex = mManager.allocBackStackIndex(this);
            } else {
                mIndex = -1;
            }
            mManager.enqueueAction(this, allowStateLoss);
            return mIndex;
        }
    
    • mManager.allocBackStackIndex(this):将BackStackRecord添加到mBackStackIndices中。
        public int allocBackStackIndex(BackStackRecord bse) {
            synchronized (this) {
                if (mAvailBackStackIndices == null || mAvailBackStackIndices.size() <= 0) {
                    if (mBackStackIndices == null) {
                        mBackStackIndices = new ArrayList<BackStackRecord>();
                    }
                    int index = mBackStackIndices.size();
                    mBackStackIndices.add(bse);
                    return index;
    
                } else {
                    int index = mAvailBackStackIndices.remove(mAvailBackStackIndices.size()-1);
                    mBackStackIndices.set(index, bse);
                    return index;
                }
            }
        }
    
    • mManager.enqueueAction(this, allowStateLoss):将实现OpGenerator的BackStackRecord添加到了mPendingActions。
        public void enqueueAction(OpGenerator action, boolean allowStateLoss) {
            //code..
            synchronized (this) {
                //code..
                mPendingActions.add(action);
                scheduleCommit();
            }
        }
        
        //调用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);
                    updateOnBackPressedCallbackEnabled();
                }
            }
        }
    
    • FragmentManagerImpl.mExecCommit源码
        Runnable mExecCommit = new Runnable() {
            @Override
            public void run() {
                execPendingActions();
            }
        };
    
        public boolean execPendingActions() {
            ensureExecReady(true);
            boolean didSomething = false;
            while (generateOpsForPendingActions(mTmpRecords, mTmpIsPop)) {
                mExecutingActions = true;
                try {
                    removeRedundantOperationsAndExecute(mTmpRecords, mTmpIsPop);
                } finally {
                    cleanupExec();
                }
                didSomething = true;
            }
            updateOnBackPressedCallbackEnabled();
            doPendingDeferredStart();
            burpActive();
            return didSomething;
        }
    
    • generateOpsForPendingActions(mTmpRecords, mTmpIsPop):将mPendingActions数据添加到mTmpRecords,赋值mTmpIsPop值为false,清空mPendingActions数据并删除handler中的mExecCommit
        private boolean generateOpsForPendingActions(ArrayList<BackStackRecord> records, ArrayList<Boolean> isPop) {
            boolean didSomething = false;
            synchronized (this) {
                final int numActions = mPendingActions.size();
                for (int i = 0; i < numActions; i++) {
                    didSomething |= mPendingActions.get(i).generateOps(records, isPop);
                }
                mPendingActions.clear();
                mHost.getHandler().removeCallbacks(mExecCommit);
            }
            return didSomething;
        }
    
        @Override
        public boolean generateOps(ArrayList<BackStackRecord> records, ArrayList<Boolean> isRecordPop) {
            records.add(this);
            isRecordPop.add(false);
            if (mAddToBackStack) {
                mManager.addBackStackState(this);
            }
            return true;
        }
    
    • removeRedundantOperationsAndExecute(mTmpRecords, mTmpIsPop):通过调用executeOpsTogether方法来执行添加的所有任务。
    • 在moveToState方法中调用FragmentManager中dispatchxxx方法。而这些正好是和activity的生命周期对应起来,也就是说这些方法是随着activity进入到不同的生命周期而被调用的,即mCurState的值是被这些方法触发设置的。
        private void removeRedundantOperationsAndExecute(ArrayList<BackStackRecord> records, ArrayList<Boolean> isRecordPop) {
            //code...
            final int numRecords = records.size();
            int startIndex = 0;
            for (int recordNum = 0; recordNum < numRecords; recordNum++) {
                    //code...
                    int reorderingEnd = recordNum + 1;
                    //code...
                    executeOpsTogether(records, isRecordPop, recordNum, reorderingEnd);
                    startIndex = reorderingEnd;
                    recordNum = reorderingEnd - 1;
            }
            //code...
        }
    
        //执行添加的所有任务
        private void executeOpsTogether(ArrayList<BackStackRecord> records, ArrayList<Boolean> isRecordPop, int startIndex, int endIndex) {
            //code...
            executeOps(records, isRecordPop, startIndex, endIndex);
            //code...
        }
    
        //入栈或者出栈操作
        private static void executeOps(ArrayList<BackStackRecord> records, ArrayList<Boolean> isRecordPop, int startIndex, int endIndex) {
            for (int i = startIndex; i < endIndex; i++) {
                final BackStackRecord record = records.get(i);
                //默认存储为false
                final boolean isPop = isRecordPop.get(i);
                if (isPop) {
                    record.bumpBackStackNesting(-1);
                    boolean moveToState = i == (endIndex - 1);
                    record.executePopOps(moveToState);
                } else {
                    record.bumpBackStackNesting(1);
                    record.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.fragment;
                if (f != null) {
                    f.setNextTransition(mTransition, mTransitionStyle);
                }
                switch (op.cmd) {
                    case OP_ADD:
                        f.setNextAnim(op.enterAnim);
                        mManager.addFragment(f, false);
                        break;
                    case OP_REMOVE:
                        f.setNextAnim(op.exitAnim);
                        mManager.removeFragment(f);
                        break;
                    case OP_HIDE:
                        f.setNextAnim(op.exitAnim);
                        mManager.hideFragment(f);
                        break;
                    case OP_SHOW:
                        f.setNextAnim(op.enterAnim);
                        mManager.showFragment(f);
                        break;
                    case OP_DETACH:
                        f.setNextAnim(op.exitAnim);
                        mManager.detachFragment(f);
                        break;
                    case OP_ATTACH:
                        f.setNextAnim(op.enterAnim);
                        mManager.attachFragment(f);
                        break;
                    case OP_SET_PRIMARY_NAV:
                        mManager.setPrimaryNavigationFragment(f);
                        break;
                    case OP_UNSET_PRIMARY_NAV:
                        mManager.setPrimaryNavigationFragment(null);
                        break;
                    default:
                        throw new IllegalArgumentException("Unknown cmd: " + op.cmd);
                }
                if (!mReorderingAllowed && op.cmd != OP_ADD && f != null) {
                    mManager.moveFragmentToExpectedState(f);
                }
            }
            if (!mReorderingAllowed) {
                mManager.moveToState(mManager.mCurState, true);
            }
        }
    

    总结

    • 通过源码得知add、remove、replacea、hide、show等方法中只是做了赋值操作,并没有对Fragment进行任何操作。
    • commit()将FragmentTransaction的实现类BackStackRecord添加到mBackStackIndices集合中。
    • 通过enqueueAction()方法将实现OpGenerator的BackStackRecord添加到了mPendingActions中,并通过scheduleCommit方法调用handler.post(mExecCommit)。
    • mExecCommit是一个Runnable对象,在run方法中调用execPendingActions()方法。
    • execPendingActions()方法将mPendingActions中数据添加到mTmpRecords中,并将mTmpIsPop赋值为false,清空mPendingActions数据并删除handler中mExecCommit对象;通过调用executeOpsTogether方法来执行添加的所有任务。

    相关文章

      网友评论

          本文标题:组件之Fragment源码解析

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