Fragment的管理(FragmentManager)

2020-11-27  本文已影响0人  feifei_fly

最近在开发过程中发现自己对Fragment的管理原理理解的很模糊,于是以Android-28为基础,对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();
        }
    }
}


下面我们重点看一下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;
    }

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时 会顺序执行

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.onCreate()
Fragment.onAttach()
(1) 提取Fragment的ContainerId 对应的ViewGroup

(2) 调用Fragment的onCreateView()获取Fragment中的的View

(3) 将Framgnet中的View 添加到ContrainerView当中

(4) 调用Fragment的OnViewCreated() 

(5) 调用Fragment的onActivityCreated() 
Fragment.onStart()

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())。执行过程如下:

- FragmentA执行OP_REMOVE 被移除
- FragmentB执行OP_ADD 被添加 
当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

上一篇下一篇

猜你喜欢

热点阅读