Fragment源码学习(一)

Fragment源码学习(一)

首先看一下 Fragment 的基本用法

        FragmentManager fragmentManager = getSupportFragmentManager();
        FragmentTransaction transaction = fragmentManager.beginTransaction();
        transaction.add(R.id.frameLayout, Bug5Fragment.newIntance(), Bug5Fragment.class.getName());
        transaction.commit();

第一步: getSupportFragmentManager()

 首先看一下 getSupportFragmentManager()方法,该方法在 FragmentActivity,可以看到FragmentActivity的间接父类是 Activity

public class FragmentActivity extends ComponentActivity implements
        ViewModelStoreOwner,
        ActivityCompat.OnRequestPermissionsResultCallback,
        ActivityCompat.RequestPermissionsRequestCodeValidator {

        final FragmentController mFragments = FragmentController.createController(new   HostCallbacks());

        public FragmentManager getSupportFragmentManager() {
            return mFragments.getSupportFragmentManager();
        }

}
public class ComponentActivity extends Activity
        implements LifecycleOwner, KeyEventDispatcher.Component {

 在 FragmentActivity中 getSupportFragmentManager()方法调用了 FragmentController 的 getSupportFragmentManager()方法,而 mFragments 又是FragmentActivity的类成员变量,所以在创建 FragmentActivity类的同时将会调用 createController()方法创建FragmentController实例 mFragments,下面来一张 getSupportFragmentManager的流程图

第二步: beginTransaction()

接下来看 beginTransaction() 的操作流程 

public abstract class FragmentManager {
    
    @NonNull
    public abstract FragmentTransaction beginTransaction();

FragmentManager 是一个抽象类,它的实现是它的子类 FragmentManagerImpl

/**
 * Container for fragments associated with an activity.
 */
final class FragmentManagerImpl extends FragmentManager implements LayoutInflater.Factory2 {
    static boolean DEBUG = false;
    static final String TAG = "FragmentManager";

    //mPendingActions 表示待执行动作
    ArrayList<OpGenerator> mPendingActions;

    //mAdded 是 mActive 的子集表示活着的 fragments
    final ArrayList<Fragment> mAdded = new ArrayList<>();
    
    //mActive 不仅有活着的 fragments 还有在返回栈中等待被复原的 fragments。
    SparseArray<Fragment> mActive;


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

}

可以看到 beginTransaction()方法实际上是直接new了一个 BacStackRecord,BackStackRecord 实现了抽象类 FragmentTransaction

/**
 * Entry of an operation on the fragment back stack.
 */
final class BackStackRecord extends FragmentTransaction implements
        FragmentManager.BackStackEntry, FragmentManagerImpl.OpGenerator {
    static final String TAG = FragmentManagerImpl.TAG;

    final FragmentManagerImpl mManager;

    //Op类封装了Fragment及其对应的操作指令cmd(add、remove、replace等)
    static final class Op {
        int cmd;
        Fragment fragment;
        int enterAnim;
        int exitAnim;
        int popEnterAnim;
        int popExitAnim;

        Op() {
        }

        Op(int cmd, Fragment fragment) {
            this.cmd = cmd;
            this.fragment = fragment;
        }
    }

    //数组mOps保存了FragmentTransaction的一系列原子操作
    //add、remove、replace等
    ArrayList<Op> mOps = new ArrayList<>();

    //构造函数将FragmentManagerImpl和BackStackRecord绑定
    public BackStackRecord(FragmentManagerImpl manager) {
        mManager = manager;
    }

}

第三步:事务操作 add、remove、replace

接下来看一下FragmentTransaction的 add、remove、replace等一系列原子操作是怎么实现的

final class BackStackRecord extends FragmentTransaction implements
        FragmentManager.BackStackEntry, FragmentManagerImpl.OpGenerator {

    ArrayList<Op> mOps = new ArrayList<>();

    @Override
    public FragmentTransaction add(int containerViewId, Fragment fragment, @Nullable String tag) {
        doAddOp(containerViewId, fragment, tag, OP_ADD);
        return this;
    }

    @Override
    public FragmentTransaction remove(Fragment fragment) {
        addOp(new Op(OP_REMOVE, fragment));
        return this;
    }

    @Override
    public FragmentTransaction replace(int containerViewId, Fragment fragment,
            @Nullable String tag) {
        if (containerViewId == 0) {
            throw new IllegalArgumentException("Must use non-zero containerViewId");
        }
        doAddOp(containerViewId, fragment, tag, OP_REPLACE);
        return this;
    }

    private void doAddOp(int containerViewId, Fragment fragment, @Nullable String tag, int opcmd) {
        ......
        fragment.mFragmentManager = mManager;
        if (tag != null) {
            ......
            fragment.mTag = tag;
        }
        if (containerViewId != 0) {
            ......
            fragment.mContainerId = fragment.mFragmentId = containerViewId;
        }
        addOp(new Op(opcmd, fragment));
    }

    void addOp(Op op) {
        //将一系列FragmentTransacton操作添加到 mOps数组
        mOps.add(op);
        op.enterAnim = mEnterAnim;
        op.exitAnim = mExitAnim;
        op.popEnterAnim = mPopEnterAnim;
        op.popExitAnim = mPopExitAnim;
    }
}

通过以上源码可以看到 FragmentTransaction的add、remove、replace等方法的逻辑都是一样的,这些方法都没有直接对Fragment进行添加或者删除等操作,而是将我们要操作的Fragment同它的指令cmd封装到一个Op类里,每一个原子操作都会new出一个对应指令的Op对象,最后将这一些列的原子操作对应得Op对象都添加到一个Op数组 mOps 中 ,现在我们可以猜想到真正的add、remove、replace操作应该是在commit方法中,接下来我们看一下commit方法

第四步:commit()

讲 commit()流程之前先了解下 FragmentManangerImpl的几个变量

final class FragmentManagerImpl extends FragmentManager implements LayoutInflater.Factory2 {

    //mPendingActions 待执行动作
    ArrayList<OpGenerator> mPendingActions;

    //mAdded 是 mActive 的子集表示活着的 fragments
    final ArrayList<Fragment> mAdded = new ArrayList<>();

    //mActive 不仅有活着的 fragments 还有在返回栈中等待被复原的 fragments。
    SparseArray<Fragment> mActive;

    //mTmpRecords用来临时存储所有待执行的动作(mPendingActions)生成的 BackStackRecord,
    //mTmpIsPop用来存储 BackStackRecord 是否为出栈
    ArrayList<BackStackRecord> mTmpRecords;//用于优化执行的临时变量
    ArrayList<Boolean> mTmpIsPop;//用于优化执行的临时变量
}

通过commit()方法将一系列事务操作最终交给 FragmentManager 执行

final class BackStackRecord extends FragmentTransaction implements
        FragmentManager.BackStackEntry, FragmentManagerImpl.OpGenerator {

    final FragmentManagerImpl mManager;

    @Override
    public int commit() {
        return commitInternal(false);
    }
    int commitInternal(boolean allowStateLoss) {
        //commit()方法只能够执行一次
        if (mCommitted) throw new IllegalStateException("commit already called");
        ......
        mCommitted = true;
        if (mAddToBackStack) {
            //最终交给FragmentManager执行
            mIndex = mManager.allocBackStackIndex(this);
        } else {
            mIndex = -1;
        }
        //最终会交给FragmentManager去执行,这里第一个参数传入BackStackRecord本身
        //因为BackStackRecord 实现了接口 OpGenerator
        mManager.enqueueAction(this, allowStateLoss);
        return mIndex;
    }
}

在 FragmentManger中异步执行 commit()操作

final class FragmentManagerImpl extends FragmentManager implements LayoutInflater.Factory2 {
    
    public void enqueueAction(OpGenerator action, boolean allowStateLoss) {
        if (!allowStateLoss) {
            checkStateLoss();
        }
        synchronized (this) {
            ......
            if (mPendingActions == null) {
                mPendingActions = new ArrayList<>();
            }
            //将待执行的操作添加到mPendingActions数组中
            mPendingActions.add(action);
            scheduleCommit();//执行commit(这里是异步执行)
        }
    }

    void scheduleCommit() {
        synchronized (this) {
            boolean postponeReady =
                    mPostponedTransactions != null && !mPostponedTransactions.isEmpty();
            boolean pendingReady = mPendingActions != null && mPendingActions.size() == 1;
            if (postponeReady || pendingReady) {
                mHost.getHandler().removeCallbacks(mExecCommit);
                //获取主线程的Handler通过post方法将要执行的操作加入主线程Looper所在的
                //消息队列中,等待执行。
                mHost.getHandler().post(mExecCommit);
            }
        }
    }
    Runnable mExecCommit = new Runnable() {
        @Override
        public void run() {
            execPendingActions();
        }
    };

    /**
     * Only call from main thread!
     */
    public boolean execPendingActions() {
        ensureExecReady(true);
        boolean didSomething = false;
        //先将 mPendingActions 数组中的 BackStackRecord对象添加到 mTemRecords 数组
        while (generateOpsForPendingActions(mTmpRecords, mTmpIsPop)) {
            mExecutingActions = true;
            try {
                //这里会将mOps数组中的一系列命令进行整合
                removeRedundantOperationsAndExecute(mTmpRecords, mTmpIsPop);
            } finally {
                cleanupExec();
            }
            didSomething = true;
        }
        doPendingDeferredStart();
        burpActive();
        return didSomething;
    }
}

看一下 generateOpsForPendingActions(mTmpRecords, mTmpIsPop) 具体执行了什么

    private boolean generateOpsForPendingActions(ArrayList<BackStackRecord> records,
            ArrayList<Boolean> isPop) {
        boolean didSomething = false;
        synchronized (this) {
            if (mPendingActions == null || mPendingActions.size() == 0) {
                return false;
            }

            final int numActions = mPendingActions.size();
            for (int i = 0; i < numActions; i++) {
                //最终会调用 BackStackRecord的 generateOps()方法
                //注意:这里didSomething将始终返回true!
                didSomething |= mPendingActions.get(i).generateOps(records, isPop);
            }
            mPendingActions.clear();
            mHost.getHandler().removeCallbacks(mExecCommit);
        }
        return didSomething;
    }
final class BackStackRecord extends FragmentTransaction implements
        FragmentManager.BackStackEntry, FragmentManagerImpl.OpGenerator {
    
@Override
    public boolean generateOps(ArrayList<BackStackRecord> records, ArrayList<Boolean> isRecordPop) {
        //将 BackStackRecord添加到 mTmpRecords 数组中
        records.add(this);
        isRecordPop.add(false);
        if (mAddToBackStack) {
            mManager.addBackStackState(this);
        }
        return true;
    }
}

removeRedundantOperationsAndExecute(mTmpRecords, mTmpIsPop)方法最终会执行到 FragmentManagerImpl  的 executeOpsTogether 方法

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();
        }
        //将当前所有活着的 fragments 添加到mTempAddedFragments数组中
        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) {
                //expandOps()方法将对指令进行整合,重点关注replace
                oldPrimaryNav = record.expandOps(mTmpAddedFragments, oldPrimaryNav);
            } else {
                oldPrimaryNav = record.trackAddedFragmentsInPop(mTmpAddedFragments, oldPrimaryNav);
            }
            addToBackStack = addToBackStack || record.mAddToBackStack;
        }
        mTmpAddedFragments.clear();

        if (!allowReordering) {
            FragmentTransition.startTransitions(this, records, isRecordPop, startIndex, endIndex,
                    false);
        }
        //该方法才会真正地执行 Op 指令(add、remove等)
        executeOps(records, isRecordPop, startIndex, endIndex);
       ......
    }

最后看一下Op指令(add、remove、replace等)的整合与执行操作

final class BackStackRecord extends FragmentTransaction implements
        FragmentManager.BackStackEntry, FragmentManagerImpl.OpGenerator {
    //mOps保存了所有事务操作
    ArrayList<Op> mOps = new ArrayList<>();

    Fragment expandOps(ArrayList<Fragment> added, Fragment oldPrimaryNav) {
        for (int opNum = 0; opNum < mOps.size(); opNum++) {
            //第一层循环遍历mOps数组中所有的Op对象
            final Op op = mOps.get(opNum);
            switch (op.cmd) {
               ......
                case OP_REPLACE: {
                    //获取Op对象里需要执行replace操作的Fragment
                    final Fragment f = op.fragment;
                    //获取对应Fragment的父容器id
                    final int containerId = f.mContainerId;
                    //标记该Fragment是否已经被添加
                    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) {
                                //id为mContainerId 的父容器中如果已经添加过了该Fragment
                                //就将标记位置为true
                                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;
                                }
                                //如果父容器中尚未添加该Fragment就new出一个
                                //指令cmd为remove的Op对象,将该对象插入到opNum处
                                final Op removeOp = new Op(OP_REMOVE, old);
                                removeOp.enterAnim = op.enterAnim;
                                removeOp.popEnterAnim = op.popEnterAnim;
                                removeOp.exitAnim = op.exitAnim;
                                removeOp.popExitAnim = op.popExitAnim;
                                mOps.add(opNum, removeOp);
                                added.remove(old);
                                opNum++;
                            }
                        }
                    }
                    if (alreadyAdded) {
                        //如果该Fragment已经添加就直接将该Op对象(指令为replace)移除
                        mOps.remove(opNum);
                        opNum--;
                    } else {
                        //如果该Fragment没有添加将对应的replace指令改为add
                        //注意在该replace指令前已经添加了一个包含remove指令的Op对象
                        //所以最终执行的操作是先 remove 再 add
                        op.cmd = OP_ADD;
                        added.add(f);
                    }
                }
                break;
                case OP_SET_PRIMARY_NAV: {
                    ......
                }
                break;
            }
        }
        return oldPrimaryNav;
    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值