美文网首页
Fragment的管理(FragmentManager)

Fragment的管理(FragmentManager)

作者: feifei_fly | 来源:发表于2020-11-27 14:44 被阅读0次

    最近在开发过程中发现自己对Fragment的管理原理理解的很模糊,于是以Android-28为基础,对Fragment的管理做了一下简单梳理,记录在此,方便后面查阅。

    本文主要弄清下面几个问题:

    • Transation()到底做了什么事情
    • Replace()操作,Fragment到底是什么显示出来的。
    • popBackStack()上一个Fragment是如何恢复的。

    一、事务Transation到底做了哪些事情

    首先明确一点:所有可以使用Fragment的Activity都是FragmentActivity的子类。因为只有在FragmentActivity中才有FragmentManager。而Fragment是由FragmentManager来管理的。

    getFragmentManager()获取到的FragmentManager支持原生的Fragment,
    
    getSupportFragmentManager()支持的是v4包的Fragment。
    
    

    1.1 FragmentManagerImpl 是 FragmentManager的实现类

    在FragmentAactivity这个类下面,当我们调用getSupportManager的时候

    public class FragmentActivity extends BaseFragmentActivityJB implements
            ActivityCompat.OnRequestPermissionsResultCallback,
            ActivityCompatApi23.RequestPermissionsRequestCodeValidator {
        ···
    final FragmentController mFragments = FragmentController.createController(new HostCallbacks());
        
        ···
    
        public FragmentManager getSupportFragmentManager() {
            return mFragments.getSupportFragmentManager();
        }
        ···
    }
    

    我们可以看到FragmentActivity里面有一个FragmentController,这个FragmentController定义了所有对Fragment的管理操作,包括我们的Activity在onCreate,onResume,onDestroy等各种生命周期或回调对Fragment的影响,都是由这个类来控制的。

    public class FragmentController {
        private final FragmentHostCallback<?> mHost;
    
        /**
         * Returns a {@link FragmentController}.
         */
        public static final FragmentController createController(FragmentHostCallback<?> callbacks) {
            return new FragmentController(callbacks);
        }
    
        /**
         * Returns a {@link FragmentManager} for this controller.
         */
        public FragmentManager getSupportFragmentManager() {
            //获取到FragmentManager对象
            return mHost.getFragmentManagerImpl();
        }
    

    FragmentHostCallback是一个抽象类,负责调用各种各样的回调。
    HostCallbacks是FragmentActivity里面的一个继承FragmentHostCallback的内部类。下面我们来看看FragmentHostCallback的默认实现

    public abstract class FragmentHostCallback<E> extends FragmentContainer {
        private final Activity mActivity;
        ···
        // 实例化FragmentManager对象,FragmentManagerImpl是继承自FragmentManager抽象类的,对FragmentManager的各种方法提供具体实现
        final FragmentManagerImpl mFragmentManager = new FragmentManagerImpl();
        ···
    }
    

    至此我们找到了Fragment的实现类FragmentManagerImpl

    FragmentManagerImpl里面的具体实现就是有关Fragment是如何运行的,各种各样的生命周期,判断Fragment的不同状态,切换状态,Transaction只是用作记录对Fragment的操作记录,最终调用commit的时候,实际上调用的还是FragmentManagerImpl的方法
    
    

    1.2、 FragmentTransaction 是操作Fragment的桥梁。

    每次我们对Fragment进行操作 都是通过FragmentTransaction这个类来实现。

    FragmentTransaction的一些常用使用方式:

    //添加Fragment到FragmentList中
    private void addFragment(Fragment fragment, String tag){
            FragmentManager fragmentManager = getSupportFragmentManager();
            FragmentTransaction transaction = fragmentManager.beginTransaction();
            transaction.add(R.id.fragment_container,fragment,tag);
            transaction.commit();
        }
    
    // 清空fragmentList的所有Fragment,替换成新的Fragment,注意Fragment里面的坑
    private void replaceFragment(Fragment fragment, String tag){
            FragmentManager fragmentManager = getSupportFragmentManager();
            FragmentTransaction transaction = fragmentManager.beginTransaction();
            transaction.replace(R.id.fragment_container,fragment,tag);
            transaction.commit();
        }
    
    //移除指定的Fragment
    private void removeFragment(Fragment fragment){
            FragmentManager fragmentManager = getSupportFragmentManager();
            FragmentTransaction transaction = fragmentManager.beginTransaction();
            transaction.remove(fragment);
            transaction.commit();
        }
    
    //把Fragment设置成显示状态,但是并没有添加到FragmentList中
    private void showFragment(Fragment fragment){
            FragmentManager fragmentManager = getSupportFragmentManager();
            FragmentTransaction transaction = fragmentManager.beginTransaction();
            transaction.show(fragment);
            transaction.commit();
        }
    
    //把Fragment设置成显示状态,但是并没有添加到FragmentList中
    private void hideFragment(Fragment fragment){
            FragmentManager fragmentManager = getSupportFragmentManager();
            FragmentTransaction transaction = fragmentManager.beginTransaction();
            transaction.hide(fragment);
            transaction.commit();
        }
    
    // 效果和show相近,创建视图,添加到containerid指定的Added列表,FragmentList依然保留,但是会引起生命周期的变化
    private void attachFragment(Fragment fragment){
            FragmentManager fragmentManager = getSupportFragmentManager();
            FragmentTransaction transaction = fragmentManager.beginTransaction();
            transaction.attach(fragment);
            transaction.commit();
        }
    
    // 效果和hide相近,清除视图,从containerid指定的Added列表移除,FragmentList依然保留,但是会引起生命周期的变化
    private void detachFragment(Fragment fragment){
            FragmentManager fragmentManager = getSupportFragmentManager();
            FragmentTransaction transaction = fragmentManager.beginTransaction();
            transaction.detach(fragment);
            transaction.commit();
        }
    

    核心敲重点:

    Transaction只是用作记录对Fragment的操作记录,最终调用commit的时候,实际上调用的还是FragmentManagerImpl的方法
    

    FragmentManager.beginTransaction() 返回的是一个BackStackRecord的实例,而BackStackRecord继承自FragmentTransaction

    // FragmentManager 的实现类
    final class FragmentManagerImpl extends FragmentManager implements LayoutInflaterFactory {
        ···
        @Override
        public FragmentTransaction beginTransaction() {
            // 每次的FragmentTransaction都是独立的
            return new BackStackRecord(this);
        }
        ···
    }
    
    // Transaction的实现类
    final class BackStackRecord extends FragmentTransaction implements
            FragmentManager.BackStackEntry, FragmentManagerImpl.OpGenerator {
    
        // 初始化的时候传入FragmentManagerImpl 的实例
        public BackStackRecord(FragmentManagerImpl manager) {
            mManager = manager;
        }
    
        @Override
        public int commit() {
            //返回栈id,要是不添加进栈,返回-1
            return commitInternal(false);
        }
    
        int commitInternal(boolean allowStateLoss) {
           // 提交以后无法再次提交
            if (mCommitted) throw new IllegalStateException("commit already called");
            if (FragmentManagerImpl.DEBUG) {
                Log.v(TAG, "Commit: " + this);
                LogWriter logw = new LogWriter(TAG);
                PrintWriter pw = new PrintWriter(logw);
                dump("  ", null, pw, null);
            }
            mCommitted = true;
            //是否要添加到回退栈
            if (mAddToBackStack) {
                // 在回退栈中分配栈ID
                mIndex = mManager.allocBackStackIndex(this);
            } else {
                mIndex = -1;
            }
            //执行这个Transaction
            mManager.enqueueAction(this, allowStateLoss);
            return mIndex;
        }
    
    }
    

    FragmentTransaction 支持一系列的操作

    #将一个fragment实例添加到Activity里面指定id的容器中
    add(Fragment fragment, String tag)
    add(int containerViewId, Fragment fragment)
    add(int containerViewId, Fragment fragment, String tag);
     #将一个fragment实例从FragmentManager的FragmentList中移除
    remove(Fragment fragment);
    #只控制Fragment的隐藏
    hide(Fragment fragment)
    #只控制Fragment的显示
    show(Fragment fragment)
    #清除视图,从containerid指定的Added列表移除,FragmentList依然保留
    detach(Fragment fragment)
    #创建视图,添加到containerid指定的Added列表,FragmentList依然保留
    attach(Fragment fragment)
    #替换containerViewId中的fragment,它会把containerViewId中所有fragment删除,然后添加当前的fragment
    replace(int containerViewId, Fragment fragment)
    replace(int containerViewId, Fragment fragment, String tag)
    

    FragmentTransaction 其实就是一个容器,内部维护一个mOps数组,执行add(),remove(),replace()操作时,所做的就是讲这些操作封装成Op对象保存在mOps数组中。

    public abstract class FragmentTransaction {
    
        static final int OP_NULL = 0;
        static final int OP_ADD = 1;
        static final int OP_REPLACE = 2;
        static final int OP_REMOVE = 3;
        static final int OP_HIDE = 4;
        static final int OP_SHOW = 5;
        static final int OP_DETACH = 6;
        static final int OP_ATTACH = 7;
        static final int OP_SET_PRIMARY_NAV = 8;
        static final int OP_UNSET_PRIMARY_NAV = 9;
        static final int OP_SET_MAX_LIFECYCLE = 10;
    
     static final class Op {
            int mCmd;
            Fragment mFragment;
    
    
            Op() {
            }
    
            Op(int cmd, Fragment fragment) {
                this.mCmd = cmd;
                this.mFragment = fragment;
               
            }
    }
    
        ArrayList<Op> mOps = new ArrayList<>();
        
    
        void addOp(Op op) {
            mOps.add(op);
            op.mEnterAnim = mEnterAnim;
            op.mExitAnim = mExitAnim;
            op.mPopEnterAnim = mPopEnterAnim;
            op.mPopExitAnim = mPopExitAnim;
        }
    
        /**
         * Calls {@link #add(int, Fragment, String)} with a 0 containerViewId.
         */
        @NonNull
        public FragmentTransaction add(@NonNull Fragment fragment, @Nullable String tag)  {
            doAddOp(0, fragment, tag, OP_ADD);
            return this;
        }
    
         @NonNull
        public FragmentTransaction remove(@NonNull Fragment fragment) {
            addOp(new Op(OP_REMOVE, fragment));
    
            return this;
        }
    }
    

    当执行FragmentTransaction.commit时,最终会调用FragmentManager.enqueueAction(),将BackStackRecord加入到FragmentManager的一个执行队列中,这个操作队列会在主线程中顺序被执行。

    final class BackStackRecord{
       @Override
        public int commit() {
            return commitInternal(false);
        }
        
        int commitInternal(boolean allowStateLoss) {
            if (mCommitted) throw new IllegalStateException("commit already called");
            if (FragmentManagerImpl.DEBUG) {
                Log.v(TAG, "Commit: " + this);
                LogWriter logw = new LogWriter(TAG);
                PrintWriter pw = new PrintWriter(logw);
                dump("  ", pw);
                pw.close();
            }
            mCommitted = true;
            if (mAddToBackStack) {
                mIndex = mManager.allocBackStackIndex(this);
            } else {
                mIndex = -1;
            }
            mManager.enqueueAction(this, allowStateLoss);
            return mIndex;
        }
    }
    

    二、BackStackRecord的执行

    BackStackRecord加入到FragmentManager队列中是如何被执行的,Fragment又是如何显示出来的呢?(add操作)

    FragmentManagerImpl类

      /**
         * Adds an action to the queue of pending actions.
         *
         * @param action the action to add
         * @param allowStateLoss whether to allow loss of state information
         * @throws IllegalStateException if the activity has been destroyed
         */
        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) {
                    mPendingActions = new ArrayList<>();
                }
                mPendingActions.add(action);
                scheduleCommit();
            }
        }
        
    
        
          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();
                }
            }
        }
        
           Runnable mExecCommit = new Runnable() {
            @Override
            public void run() {
                execPendingActions();
            }
        };
        
          /**
         * Only call from main thread!
         */
        public boolean execPendingActions() {
            ensureExecReady(true);
    
            removeRedundantOperationsAndExecute(mTmpRecords, mTmpIsPop);
              
         
            return didSomething;
        }
        
        private void removeRedundantOperationsAndExecute(ArrayList<BackStackRecord> records,ArrayList<Boolean> isRecordPop) {
                       executeOpsTogether(records, isRecordPop, recordNum, reorderingEnd);                          
            
        }
        
          private void executeOpsTogether(ArrayList<BackStackRecord> records,
                                        ArrayList<Boolean> isRecordPop, int startIndex, int endIndex) {
            final boolean allowReordering = records.get(startIndex).mReorderingAllowed;
            boolean addToBackStack = false;
            if (mTmpAddedFragments == null) {
                mTmpAddedFragments = new ArrayList<>();
            } else {
                mTmpAddedFragments.clear();
            }
            mTmpAddedFragments.addAll(mAdded);
            Fragment oldPrimaryNav = getPrimaryNavigationFragment();
            for (int recordNum = startIndex; recordNum < endIndex; recordNum++) {
                final BackStackRecord record = records.get(recordNum);
                final boolean isPop = isRecordPop.get(recordNum);
                if (!isPop) {
                
                    //注释一:将ops操作 拆解为基本操作的序列
                    oldPrimaryNav = record.expandOps(mTmpAddedFragments, oldPrimaryNav);
                } else {
                    oldPrimaryNav = record.trackAddedFragmentsInPop(mTmpAddedFragments, oldPrimaryNav);
                }
                addToBackStack = addToBackStack || record.mAddToBackStack;
            }
            mTmpAddedFragments.clear();
    
     
            executeOps(records, isRecordPop, startIndex, endIndex);
    
        
        }
        
        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);
            final boolean isPop = isRecordPop.get(i);
            if (isPop) {
                record.bumpBackStackNesting(-1);
           
                boolean moveToState = i == (endIndex - 1);
                //注释二:出栈操作,执行executePopOps
                record.executePopOps(moveToState);
            } else {
                record.bumpBackStackNesting(1);
                //注释三:入栈操作,执行executeOps()
                record.executeOps();
            }
        }
    }
    
    
    
    • 注释一:record.expandOps()会将ops操作 拆解为更简单的基本操作序列,如replace()操作,会被拆解为N个Remove+1个Add操作,保存在mOps数组中。
    • 注释二:如果当前BackStackRecord是出栈操作,则执行record.executePopOps()
    • 注释三:如果当前BackStackRecord是入栈操作,则执行record.executeOps()

    下面我们重点看一下BackStackRecord的这三个方法

    2.1、 BackStackRecord.expandOps():

    expandOps的主要作用扩展Op操作,将原始是Ops操作扩展成更基本的Ops序列,它会修改FragmentManagetImpl的mAdded数组和oldPrimaryNav

      /**
         * Expands all meta-ops into their more primitive equivalents. This must be called prior to
         * {@link #executeOps()} or any other call that operations on mOps for forward navigation.
         * It should not be called for pop/reverse navigation operations.
         *
         * <p>Removes all OP_REPLACE ops and replaces them with the proper add and remove
         * operations that are equivalent to the replace.</p>
         *
         * <p>Adds OP_UNSET_PRIMARY_NAV ops to match OP_SET_PRIMARY_NAV, OP_REMOVE and OP_DETACH
         * ops so that we can restore the old primary nav fragment later. Since callers call this
         * method in a loop before running ops from several transactions at once, the caller should
         * pass the return value from this method as the oldPrimaryNav parameter for the next call.
         * The first call in such a loop should pass the value of
         * {@link FragmentManager#getPrimaryNavigationFragment()}.</p>
         *
         * @param added Initialized to the fragments that are in the mManager.mAdded, this
         *              will be modified to contain the fragments that will be in mAdded
         *              after the execution ({@link #executeOps()}.
         * @param oldPrimaryNav The tracked primary navigation fragment as of the beginning of
         *                      this set of ops
         * @return the new oldPrimaryNav fragment after this record's ops would be run
         */
        @SuppressWarnings("ReferenceEquality")
        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:
                        //(1)ADD和ATTACH方法,仅将mFragment添加到mAdded数组
                        added.add(op.mFragment);
                        break;
                    case OP_REMOVE:
                    case OP_DETACH: {
                        //(2)REMOVE和DETACH操作,将mFragment从added数组移除,并插入OP_UNSET_PRIMARY_NAV操作,将oldPrimaryNav移除
                        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: {
                        //(3)REPLACE 将added数组中,所有mContainerId匹配的Frament移除,然后再j将当前Frament添加。replace操作 转变成了REMOVE*N+ADD的序列
                        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) {
                                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++;
                                }
                            }
                        }
                        if (alreadyAdded) {
                            mOps.remove(opNum);
                            opNum--;
                        } else {
                            op.mCmd = OP_ADD;
                            added.add(f);
                        }
                    }
                    break;
                    //(4)SET_PRIMARY_NAV 操作,更新oldPrimaryNav的值
                    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;
        }
    
    • (1)ADD和ATTACH方法,仅将mFragment添加到mAdded数组
    • (2)REMOVE和DETACH操作,将mFragment从added数组移除,并插入OP_UNSET_PRIMARY_NAV操作,将oldPrimaryNav移除。
    • (3)REPLACE 将added数组中,所有mContainerId匹配的Frament移除,然后再j将当前Frament添加。replace操作 转变成了REMOVE*N+ADD的序列。
    • (4)SET_PRIMARY_NAV 操作,更新oldPrimaryNav的值

    2.2、 BackStackRecord.executeOps() 入栈操作

    当Fragment入栈时,会执行BackStackRecord.executeOps()方法
    executeOps方法中,将Op操作 都代理到了FragmentManagerImpl对应的方法。

        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, mTransitionStyle);
                }
                switch (op.mCmd) {
                    case OP_ADD:
                        f.setNextAnim(op.mEnterAnim);
                        mManager.addFragment(f, false);
                        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.showFragment(f);
                        break;
                    case OP_DETACH:
                        f.setNextAnim(op.mExitAnim);
                        mManager.detachFragment(f);
                        break;
                    case OP_ATTACH:
                        f.setNextAnim(op.mEnterAnim);
                        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) {
                // Added fragments are added at the end to comply with prior behavior.
                mManager.moveToState(mManager.mCurState, true);
            }
        }
    

    执行OP_ADD时 会顺序执行

    • FragmentManagerImpl.addFragment()
    • FragmentManagerImpl.moveToState()
    • FragmentManagerImpl.moveFragmentToExpectedState()
    • FragmentManagerImpl.moveToState(Fragment f, int newState, int transit, int transitionStyle, boolean keepActive)

    addFragment中的核心操作 就是将将Fragmet加入到mAdded数组,同时修改Fragment对应的标志位

      public void addFragment(Fragment fragment, boolean moveToStateNow) {
            if (DEBUG) Log.v(TAG, "add: " + fragment);
            makeActive(fragment);
            if (!fragment.mDetached) {
                //将Fragmet加入到mAdded数组
                synchronized (mAdded) {
                    mAdded.add(fragment);
                }
                //修改frament中的标志位
                fragment.mAdded = true;
                fragment.mRemoving = false;
             
                if (moveToStateNow) {
                    moveToState(fragment);
                }
            }
        }
    

    操作二:调用moveToState()方法
    moveFragmentToExpectedState->moveToState()

    2.3、 FragmentManagerImpl.moveToState() 执行Fragment的状态切换

    void moveToState(Fragment f, int newState, int transit, int transitionStyle,
                         boolean keepActive) {
            // Fragments that are not currently added will sit in the onCreate() state.
            if ((!f.mAdded || f.mDetached) && newState > Fragment.CREATED) {
                newState = Fragment.CREATED;
            }
     
           
            // Don't allow the Fragment to go above its max lifecycle state
            // Ensure that Fragments are capped at CREATED instead of ACTIVITY_CREATED.
            if (f.mMaxState == Lifecycle.State.CREATED) {
                newState = Math.min(newState, Fragment.CREATED);
            } else {
                newState = Math.min(newState, f.mMaxState.ordinal());
    
            }
    
            //如果newState > Fragment当前的状态
            if (f.mState <= newState) {
              
              
                switch (f.mState) {
                    case Fragment.INITIALIZING:
                        if (newState > Fragment.INITIALIZING) {
                            if (DEBUG) Log.v(TAG, "moveto CREATED: " + f);
                 
    
                            f.mHost = mHost;
                            f.mParentFragment = mParent;
                            f.mFragmentManager = mParent != null
                                    ? mParent.mChildFragmentManager : mHost.mFragmentManager;
    
                            //(1)执行Fragment.attach()
                            f.performAttach();
                            if (f.mParentFragment == null) {
                                mHost.onAttachFragment(f);
                            } else {
                                f.mParentFragment.onAttachFragment(f);
                            }
                   
                            //(2)执行Fragmet.onCreate()
                            if (!f.mIsCreated) {
                                dispatchOnFragmentPreCreated(f, f.mSavedFragmentState, false);
                                f.performCreate(f.mSavedFragmentState);
                                dispatchOnFragmentCreated(f, f.mSavedFragmentState, false);
                            } else {
                                f.restoreChildFragmentState(f.mSavedFragmentState);
                                f.mState = Fragment.CREATED;
                            }
                        }
                        // fall through
                    case Fragment.CREATED:
                     
    
                        if (newState > Fragment.CREATED) {
                          
                            if (!f.mFromLayout) {
                                ViewGroup container = null;
                                if (f.mContainerId != 0) {
                                    
                                //(1)提取Fragment的ContainerId 对应的ViewGroup
                                container = (ViewGroup) mContainer.onFindViewById(f.mContainerId);
                         
                                // (2) 调用Fragment的onCreateView()绘制Fragment中的View
                                f.mContainer = container;
                                f.performCreateView(f.performGetLayoutInflater(
                                        f.mSavedFragmentState), container, f.mSavedFragmentState);
                                if (f.mView != null) {
                                    f.mInnerView = f.mView;
                                    f.mView.setSaveFromParentEnabled(false);
                                    //(3)将Framgnet中的View 添加到ContrainerView当中
                                    if (container != null) {
                                        container.addView(f.mView);
                                    }
                                    if (f.mHidden) {
                                        f.mView.setVisibility(View.GONE);
                                    }
                                    //(4)调用Fragment的OnViewCreated() 
                                    f.onViewCreated(f.mView, f.mSavedFragmentState);
                                    dispatchOnFragmentViewCreated(f, f.mView, f.mSavedFragmentState,
                                            false);
                        
                                    f.mIsNewlyAdded = (f.mView.getVisibility() == View.VISIBLE)
                                            && f.mContainer != null;
                                } else {
                                    f.mInnerView = null;
                                }
                            }
                            //(5)调用Fragment的onActivityCreated() 
                            f.performActivityCreated(f.mSavedFragmentState);
                            dispatchOnFragmentActivityCreated(f, f.mSavedFragmentState, false);
                            if (f.mView != null) {
                                f.restoreViewState(f.mSavedFragmentState);
                            }
                            f.mSavedFragmentState = null;
                        }
                        // fall through
                    case Fragment.ACTIVITY_CREATED:
                        //(1) 调用Fragment.onStart()
                        if (newState > Fragment.ACTIVITY_CREATED) {
                            if (DEBUG) Log.v(TAG, "moveto STARTED: " + f);
                            f.performStart();
                            dispatchOnFragmentStarted(f, false);
                        }
                        // fall through
                    case Fragment.STARTED:
                             //(1) 调用Fragment.onResume() 
                        if (newState > Fragment.STARTED) {
                            if (DEBUG) Log.v(TAG, "moveto RESUMED: " + f);
                            f.performResume();
                            dispatchOnFragmentResumed(f, false);
                            f.mSavedFragmentState = null;
                            f.mSavedViewState = null;
                        }
                }
            } else if (f.mState > newState) {
              ... //执行一些列反向的操作 
               switch (f.mState) {
                    case Fragment.RESUMED:
                        if (newState < Fragment.RESUMED) {
                            if (DEBUG) Log.v(TAG, "movefrom RESUMED: " + f);
                            f.performPause();
                            dispatchOnFragmentPaused(f, false);
                        }
                        // fall through
                    case Fragment.STARTED:
                        if (newState < Fragment.STARTED) {
                            if (DEBUG) Log.v(TAG, "movefrom STARTED: " + f);
                            f.performStop();
                            dispatchOnFragmentStopped(f, false);
                        }
                        // fall through
                    }
            
            }
    
            if (f.mState != newState) {
              
                f.mState = newState;
            }
        }
    

    Fragment 有以下几个状态:

        static final int INITIALIZING = 0;     // Not yet created.
        static final int CREATED = 1;          // Created.
        static final int ACTIVITY_CREATED = 2; // Fully created, not started.
        static final int STARTED = 3;          // Created and started, not resumed.
        static final int RESUMED = 4;          // Created started and resumed.
    

    moveToState()方法 将Fragment由当前的mState状态切换为newState状态。
    当newState>Fragment.mState 进行Fraggment的正向生命周期,当newState<Fragment.state,执行Fragment的逆向生命周期。

    以正向声明周期为例,

    • Fragment.state == INITIALIZING: 表示Not yet created, 执行操作
    Fragment.onCreate()
    Fragment.onAttach()
    
    • Fragment.state == CREATED: 表示 Created,执行操作
    (1) 提取Fragment的ContainerId 对应的ViewGroup
    
    (2) 调用Fragment的onCreateView()获取Fragment中的的View
    
    (3) 将Framgnet中的View 添加到ContrainerView当中
    
    (4) 调用Fragment的OnViewCreated() 
    
    (5) 调用Fragment的onActivityCreated() 
    
    • Fragment.state == ACTIVITY_CREATED:表示Fully created, not started,执行操作
    Fragment.onStart()
    
    • Fragment.state == STARTED ,表示 Created started and resumed.

    2.4、BackStackRecord.executePopOps()

    executePopOps()是Fragment出栈时的操作,是入栈操作的逆操作。

     void executePopOps(boolean moveToState) {
            for (int opNum = mOps.size() - 1; opNum >= 0; opNum--) {
                final Op op = mOps.get(opNum);
                Fragment f = op.mFragment;
                if (f != null) {
                    f.setNextTransition(FragmentManagerImpl.reverseTransit(mTransition),
                            mTransitionStyle);
                }
                switch (op.mCmd) {
                    case OP_ADD:
                        f.setNextAnim(op.mPopExitAnim);
                        mManager.removeFragment(f);
                        break;
                    case OP_REMOVE:
                        f.setNextAnim(op.mPopEnterAnim);
                        mManager.addFragment(f, false);
                        break;
                    case OP_HIDE:
                        f.setNextAnim(op.mPopEnterAnim);
                        mManager.showFragment(f);
                        break;
                    case OP_SHOW:
                        f.setNextAnim(op.mPopExitAnim);
                        mManager.hideFragment(f);
                        break;
                    case OP_DETACH:
                        f.setNextAnim(op.mPopEnterAnim);
                        mManager.attachFragment(f);
                        break;
                    case OP_ATTACH:
                        f.setNextAnim(op.mPopExitAnim);
                        mManager.detachFragment(f);
                        break;
                    case OP_SET_PRIMARY_NAV:
                        mManager.setPrimaryNavigationFragment(null);
                        break;
                    case OP_UNSET_PRIMARY_NAV:
                        mManager.setPrimaryNavigationFragment(f);
                        break;
                    case OP_SET_MAX_LIFECYCLE:
                        mManager.setMaxLifecycle(f, op.mOldMaxState);
                        break;
                    default:
                        throw new IllegalArgumentException("Unknown cmd: " + op.mCmd);
                }
                if (!mReorderingAllowed && op.mCmd != OP_REMOVE && f != null) {
                    mManager.moveFragmentToExpectedState(f);
                }
            }
            if (!mReorderingAllowed && moveToState) {
                mManager.moveToState(mManager.mCurState, true);
            }
        }
    

    2.5、总结一下执行replace()时 Fragment的View是如何显示出来的

    假设Actvity中当前正在显示FragmentA,此时在同一个ContainerID上执行replace(FragmentB())。执行过程如下:

    • BackStackRecord.expendOp()方法将OP_REPLACE 操作被拆分 一个OP_REMOVE和一个OP_ADD操作
    • 执行 BackStackRecord.executeOps()
    - FragmentA执行OP_REMOVE 被移除
    - FragmentB执行OP_ADD 被添加 
    
    • FragmentManagerImpl.moveToState()
    当Fragment.mState == CREATED 时,执行一下操作
    (1) 提取Fragment的ContainerId 对应的ViewGroup
    
    (2) 调用Fragment的onCreateView()获取Fragment中的的View
    
    (3) 将Framgnet中的View 添加到ContrainerView当中
    
    (4) 调用Fragment的OnViewCreated() 
    
    (5) 调用Fragment的onActivityCreated() 
    

    至此FragmentB 被添加到Activity的View树中,显示出来。

    三、Fragment是如何回退的。

    FragmentManager中有一个mBackStack数组,承载了加入回退栈中的FragmentTransaction操作

    final class FragmentManagerImpl extends FragmentManager implements LayoutInflater.Factory2
    
     ArrayList<BackStackRecord> mBackStack;//这个就是保存调用了addToBackStack方法的FragementTransaction,你看就是这个东西记录了,你commit的操作 所以当你调用了addToBackStack 以后再按返回键 就可以回到上一个fragment了
     
    }
    

    调用FragmentTransaction.addToBackStack(),便将自己加入到回退栈中。

     @NonNull
        public FragmentTransaction addToBackStack(@Nullable String name) {
            if (!mAllowAddToBackStack) {
                throw new IllegalStateException(
                        "This FragmentTransaction is not allowed to be added to the back stack.");
            }
            mAddToBackStack = true;
            mName = name;
            return this;
        }
    

    当点击Android的回退键时,会调用Activity的onBackPressed()方法。最终调用fragmentManager.popBackStackImmediate()方法。

        public void onBackPressed() {
            if (mActionBar != null && mActionBar.collapseActionView()) {
                return;
            }
    
            FragmentManager fragmentManager = mFragments.getFragmentManager();
    
            if (fragmentManager.isStateSaved() || !fragmentManager.popBackStackImmediate()) {
                finishAfterTransition();
            }
        }
    
    private boolean popBackStackImmediate(String name, int id, int flags) {
            //(1)popBackStackState 负责遍历mBackStack回退栈,将回退栈中的操作整理填充到this.mTmpRecords,并记录是否是pop回退操作(保留在this.mTmpIsPop)中
            boolean executePop = this.popBackStackState(this.mTmpRecords, this.mTmpIsPop, name, id, flags);
            if (executePop) {
                this.mExecutingActions = true;
    
                try {
                //(2) 根据this.mTmpRecords和this.mTmpIsPop 执行具体的transantion
                    this.removeRedundantOperationsAndExecute(this.mTmpRecords, this.mTmpIsPop);
                } finally {
                    this.cleanupExec();
                }
            }
    
            this.doPendingDeferredStart();
            this.burpActive();
            return executePop;
        }
    

    最终会调用到executeOps()方法,因为是回退操作,isRecordPop == true,会执行record.executePopOps(moveToState);

        private static void executeOps(ArrayList<BackStackRecord> records, ArrayList<Boolean> isRecordPop, int startIndex, int endIndex) {
            for(int i = startIndex; i < endIndex; ++i) {
                BackStackRecord record = (BackStackRecord)records.get(i);
                boolean isPop = (Boolean)isRecordPop.get(i);
                if (isPop) {
                    record.bumpBackStackNesting(-1);
                    boolean moveToState = i == endIndex - 1;
                    record.executePopOps(moveToState);
                } else {
                    record.bumpBackStackNesting(1);
                    record.executeOps();
                }
            }
    
        }
    

    executePopOps()执行原transaction操作的反向操作,如原操作是OP_ADD操作,则实际执行OP_REMOVE操作;操作是OP_REMOVE操作,则执行OP_ADD操作。

      void executePopOps(boolean moveToState) {
            for (int opNum = mOps.size() - 1; opNum >= 0; opNum--) {
                final Op op = mOps.get(opNum);
                Fragment f = op.mFragment;
                if (f != null) {
                    f.setNextTransition(FragmentManagerImpl.reverseTransit(mTransition),
                            mTransitionStyle);
                }
                switch (op.mCmd) {
                    case OP_ADD:
                        f.setNextAnim(op.mPopExitAnim);
                        mManager.removeFragment(f);
                        break;
                    case OP_REMOVE:
                        f.setNextAnim(op.mPopEnterAnim);
                        mManager.addFragment(f, false);
                        break;
                    case OP_HIDE:
                        f.setNextAnim(op.mPopEnterAnim);
                        mManager.showFragment(f);
                        break;
                    case OP_SHOW:
                        f.setNextAnim(op.mPopExitAnim);
                        mManager.hideFragment(f);
                        break;
                    case OP_DETACH:
                        f.setNextAnim(op.mPopEnterAnim);
                        mManager.attachFragment(f);
                        break;
                    case OP_ATTACH:
                        f.setNextAnim(op.mPopExitAnim);
                        mManager.detachFragment(f);
                        break;
                    case OP_SET_PRIMARY_NAV:
                        mManager.setPrimaryNavigationFragment(null);
                        break;
                    case OP_UNSET_PRIMARY_NAV:
                        mManager.setPrimaryNavigationFragment(f);
                        break;
                    case OP_SET_MAX_LIFECYCLE:
                        mManager.setMaxLifecycle(f, op.mOldMaxState);
                        break;
                    default:
                        throw new IllegalArgumentException("Unknown cmd: " + op.mCmd);
                }
                if (!mReorderingAllowed && op.mCmd != OP_REMOVE && f != null) {
                    mManager.moveFragmentToExpectedState(f);
                }
            }
            if (!mReorderingAllowed && moveToState) {
                mManager.moveToState(mManager.mCurState, true);
            }
        }
    

    注意:FragmenetTransantion.replace()操作,执行时会被拆分成remove+add操作;相应的,回退时,顺序执行执行remove和add操作。

    四、参考文章:

    https://www.jianshu.com/p/1ee67d935757
    https://www.cnblogs.com/punkisnotdead/p/4974527.html

    相关文章

      网友评论

          本文标题:Fragment的管理(FragmentManager)

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