Fragment的管理(FragmentManager)

最近在开发过程中发现自己对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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,340评论 5 467
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,762评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,329评论 0 329
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,678评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,583评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,995评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,493评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,145评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,293评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,250评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,267评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,973评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,556评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,648评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,873评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,257评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,809评论 2 339

推荐阅读更多精彩内容