Android Fragment详解

先上结论:

  1. FragmentActivity 是具有支持fragment功能的最底层的 activity, 其他什么 AppCompatActivity 都是他的子类!

  2. FragmentActivity 主要负责就是生命周期的转发,比如 onCreate onResume onDestroy 等等,这就是为什么 activity 和 fragment 状态能统一的原因了!

当然了,分发的原因就是因为 fragmentActivity 对象持有一个 fragmentController 的实例!

其实讲白了,fragmentController 就是因为它自己有一个 fragmentHostCallback,然后这个 fragmentHostCallback 还持有了 fragmentManagerImpl,

最终由 fragmentManagerImpl 的 moveToState 方法完成 fragment 生命周期的转换。

  1. fragementHostCallback 持有了 activity 的很多资源,context,handler 是其中最主要的2个。fragmentManagerImpl 就是因为拿到了 activty 的这2个资源,所以才能和 activty 互相通信的!

    为什么 fragmentManagerImpl 可以拿到 activty 的 context 和 handler?

    因为其为 fragementHostCallback 的内部类

  2. fragmentMangerImple 就是 fragmentManger 的具体实现类。moveToState方法就是在这个里面实现的

  3. FragmentTransition 也是个抽象类,他主要就是提供对外的接口函数的 add replace move 这种。BackStackRecord 就是它的具体实现类。还额外实现了 OpGenerator 接口,该接口只有一个
    generateOps(ArrayList var1, ArrayList var2) 方法。

  4. BackStackRecord 里面会有个 executeOps() 方法。这个方法就是根据不同的操作(所谓操作就是OP.CMD的那个值)来分发不同的事件,从而调用 fragmentManager的各种转换 fragment 生命周期的方法!

源码如下

一般在activity中用如下方式动态添加一个fragment:

        FragmentManager fragmentManager = getSupportFragmentManager();
        FragmentTransaction tx = fragmentManager.beginTransaction();
        //当Activity因为配置发生改变(屏幕旋转)或者内存不足被系统杀死,造成重新创建时,我们的fragment会被保存下来
        // 但是会创建新的FragmentManager,新的FragmentManager会首先会去获取保存下来的fragment队列,重建fragment队列,从而恢复之前的状态。
        if (fragmentOne == null){
            fragmentOne = FragmentOne.newInstance("fragment one");
            // 布局的id是告知FragmentManager,此fragment的位置
            // 另一方面是此fragment的唯一标识;就像我们上面通过fm.findFragmentById(R.id.id_fragment_container)查找
            tx.add(R.id.content,fragmentOne,"one");
            tx.commit();
        }

这段代码相信大家都很熟悉了,我们就来一步步跟进去看看:

    public FragmentManager getSupportFragmentManager() {
        //到这里能发现是 mFragments 返回给我们的 FragmentManager
        return this.mFragments.getSupportFragmentManager();
    }

     //继续往下跟就会发现 mFragments 是由 FragmentController 的 createController 函数构造出来的一个对象,
    //并且这个函数需要传进去一个 HostCallBack 的对象
    final FragmentController mFragments = FragmentController.createController(new FragmentActivity.HostCallbacks());

   //下面的代码就来自于FragmentController 这个类
   private final FragmentHostCallback<?> mHost;

    private FragmentController(FragmentHostCallback<?> callbacks) {
        this.mHost = callbacks;
    }

    //从这个函数就能看出来HostCallbacks 这个类肯定是FragmentHostCallback的子类了
    public static final FragmentController createController(FragmentHostCallback<?> callbacks) {
        return new FragmentController(callbacks);
    }

    //所以这个getSupportFragmentManager返回的就是 FragmentManager这个对象,并且这个对象是 mHost 的 getFragmentManagerImpl 函数返回的。
    //这里结合构造函数一看就明白了,这个mHost就是我们在activity代码里面,传进去的HostCallbacks这个对象来帮助初始化的
    public FragmentManager getSupportFragmentManager() {
        return this.mHost.getFragmentManagerImpl();
    }

      // 下面的代码在FragmentActivity里
     // 这个地方一目了然 果然我们这个 HostCallbacks 这个类是继承自 FragmentHostCallback 的,并且能看出来,我们这里把 activity 的引用也传进去了。
    // 所以能马上得出一个结论就是一个 activity 对应着一个 HostCallback 对象, 这个对象持有本身这个activity的引用。传进去以后就代表FragmentController
    //这个类的成员mHost 也持有了activity的引用
    class HostCallbacks extends FragmentHostCallback<FragmentActivity> {
        public HostCallbacks() {
            super(FragmentActivity.this);
        }

    
    //到这里就能看到FragmentHostCallback 持有了acitivty的引用 并且连activity的handler都一并持有!
    FragmentHostCallback(@Nullable Activity activity, @NonNull Context context, @NonNull Handler handler, int windowAnimations) {
        this.mFragmentManager = new FragmentManagerImpl();
        this.mActivity = activity;
        this.mContext = (Context)Preconditions.checkNotNull(context, "context == null");
        this.mHandler = (Handler)Preconditions.checkNotNull(handler, "handler == null");
        this.mWindowAnimations = windowAnimations;
    }

上面初步分析了 getSupportFragmentManager 这个方法的由来。那继续看这个方法到底是返回的什么?

    //下面的代码来源自抽象类FragmentHostCallback
    FragmentManagerImpl getFragmentManagerImpl() {
        return this.mFragmentManager;
    }

    //所以就能看出来 我们在activity中调用的 getSupportFragmentManager 这个方法最终返回的是 FragmentManagerImpl 这个类的对象了
    FragmentHostCallback(@Nullable Activity activity, @NonNull Context context, @NonNull Handler handler, int windowAnimations) {
        this.mFragmentManager = new FragmentManagerImpl();
        this.mActivity = activity;
        this.mContext = (Context)Preconditions.checkNotNull(context, "context == null");
        this.mHandler = (Handler)Preconditions.checkNotNull(handler, "handler == null");
        this.mWindowAnimations = windowAnimations;
    }

由上可知,FragmentManagerImpl 是在 FragmentHostCallback 中实例化的,且 FragmentHostCallback 持有对 fragmentActivity 以及其对应的 Handler 和 Context 的引用。

再进去看看 这个对象的 beginTransaction 方法返回的是什么:

    // 下面的代码来源自 FragmentManagerImpl
    public FragmentTransaction beginTransaction() {
        //可以看出来 返回的是BackStackRecord 这个类的对象
        return new BackStackRecord(this);
    }

// 可以看一下BackStackRecord 是 FragmentTransaction 的子类,并且实现了 BackStackEntry, OpGenerator 这两个接口
final class BackStackRecord extends FragmentTransaction implements BackStackEntry, OpGenerator {
    static final String TAG = "FragmentManager";
    final FragmentManagerImpl mManager;
    ...


// Op 为 BackStackRecord 的一个静态内部类

    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;
        }
    }

所以 begintranscation 返回的最终就是 backstackrecord 对象了。

我们继续看看这个对象的操作:

    //以下代码来源自 backstackrecord 源码
    public FragmentTransaction replace(int containerViewId, Fragment fragment) {
        return this.replace(containerViewId, fragment, (String)null);
    }

    public FragmentTransaction replace(int containerViewId, Fragment fragment, @Nullable String tag) {
        //你如果没有传进去一个有效的id的话 异常就会在这里出现了
        if (containerViewId == 0) {
            throw new IllegalArgumentException("Must use non-zero containerViewId");
        } else {
            //最终都是调用的 doAdddop 这个方法来完成操作的
            this.doAddOp(containerViewId, fragment, tag, 2);
            return this;
        }
    }

    private void doAddOp(int containerViewId, Fragment fragment, @Nullable String tag, int opcmd) {
        Class fragmentClass = fragment.getClass();
        int modifiers = fragmentClass.getModifiers();
        if (fragmentClass.isAnonymousClass() || !Modifier.isPublic(modifiers) || fragmentClass.isMemberClass() && !Modifier.isStatic(modifiers)) {
            throw new IllegalStateException("Fragment " + fragmentClass.getCanonicalName() + " must be a public static class to be  properly recreated from" + " instance state.");
        } else {
            fragment.mFragmentManager = this.mManager;
            if (tag != null) {
                if (fragment.mTag != null && !tag.equals(fragment.mTag)) {
                    throw new IllegalStateException("Can't change tag of fragment " + fragment + ": was " + fragment.mTag + " now " + tag);
                }

                fragment.mTag = tag;
            }

            if (containerViewId != 0) {
                if (containerViewId == -1) {
                    throw new IllegalArgumentException("Can't add fragment " + fragment + " with tag " + tag + " to container view with no id");
                }

                if (fragment.mFragmentId != 0 && fragment.mFragmentId != containerViewId) {
                    throw new IllegalStateException("Can't change container ID of fragment " + fragment + ": was " + fragment.mFragmentId + " now " + containerViewId);
                }

                fragment.mContainerId = fragment.mFragmentId = containerViewId;
            }

            this.addOp(new BackStackRecord.Op(opcmd, fragment));
        }
    }


    void addOp(BackStackRecord.Op op) {
        this.mOps.add(op);
        op.enterAnim = this.mEnterAnim;
        op.exitAnim = this.mExitAnim;
        op.popEnterAnim = this.mPopEnterAnim;
        op.popExitAnim = this.mPopExitAnim;
    }

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

最终其实就是将对应的 fragment 及相关信息(containerViewId,opcmd)封装后,放进 backstackrecord 对象的一个 mOps(数组列表) 中,类似,add 和 remove 方法也是对这个mOps的一些操作。

再来看看commit方法:

    //以下代码来源自 backstackrecord 源码
    public int commit() {
        return this.commitInternal(false);
    }

 int commitInternal(boolean allowStateLoss) {
        if (this.mCommitted) {
            throw new IllegalStateException("commit already called");
        } else {
            if (FragmentManagerImpl.DEBUG) {
                Log.v("FragmentManager", "Commit: " + this);
                LogWriter logw = new LogWriter("FragmentManager");
                PrintWriter pw = new PrintWriter(logw);
                this.dump("  ", (FileDescriptor)null, pw, (String[])null);
                pw.close();
            }

            this.mCommitted = true;
            if (this.mAddToBackStack) {
                this.mIndex = this.mManager.allocBackStackIndex(this);
            } else {
                this.mIndex = -1;
            }

             // 这个对象就是 final FragmentManagerImpl mManager
            // 我们在调用begin函数的时候传进去一个this指针就是用来初始化它的
            this.mManager.enqueueAction(this, allowStateLoss);
            return this.mIndex;
        }
    }

     // 下面是 FragmentManagerImpl 的源码了
    // 这个 mHost 前文介绍过持有了activity的引用,所以这里你看就是用 activity 的 handler 去执行了 mExecCommit 
    // 注意是在activity的主线程去执行的 mExecCommit
    public void enqueueAction(FragmentManagerImpl.OpGenerator action, boolean allowStateLoss) {
        if (!allowStateLoss) {
            this.checkStateLoss();
        }

        synchronized(this) {
            if (!this.mDestroyed && this.mHost != null) {
                if (this.mPendingActions == null) {
                    this.mPendingActions = new ArrayList();
                }

                this.mPendingActions.add(action);
                this.scheduleCommit();
            } else if (!allowStateLoss) {
                throw new IllegalStateException("Activity has been destroyed");
            }
        }
    }

    void scheduleCommit() {
        synchronized(this) {
            boolean postponeReady = this.mPostponedTransactions != null && !this.mPostponedTransactions.isEmpty();
            boolean pendingReady = this.mPendingActions != null && this.mPendingActions.size() == 1;
            if (postponeReady || pendingReady) {
                this.mHost.getHandler().removeCallbacks(this.mExecCommit);
                this.mHost.getHandler().post(this.mExecCommit);
            }
        }
    }

    //这个线程执行的 execPendingActions 就是这个方法 这个方法也是在 FragmentManagerImpl 里的。并不在activity里。
    //所以commit操作就是最终让activity的主线程去执行了 FragmentManagerImpl execPendingActions方法
    Runnable mExecCommit = new Runnable() {
        public void run() {
            FragmentManagerImpl.this.execPendingActions();
        }
    };


    public boolean execPendingActions() {
        this.ensureExecReady(true);

        boolean didSomething;
        for(didSomething = false; this.generateOpsForPendingActions(this.mTmpRecords, this.mTmpIsPop); didSomething = true) {
            this.mExecutingActions = true;

            try {
                this.removeRedundantOperationsAndExecute(this.mTmpRecords, this.mTmpIsPop);
            } finally {
                this.cleanupExec();
            }
        }

        this.doPendingDeferredStart();
        this.burpActive();
        return didSomething;
    }

    private void removeRedundantOperationsAndExecute(ArrayList<BackStackRecord> records, ArrayList<Boolean> isRecordPop) {
        if (records != null && !records.isEmpty()) {
            if (isRecordPop != null && records.size() == isRecordPop.size()) {
                this.executePostponedTransaction(records, isRecordPop);
                int numRecords = records.size();
                int startIndex = 0;

                for(int recordNum = 0; recordNum < numRecords; ++recordNum) {
                    boolean canReorder = ((BackStackRecord)records.get(recordNum)).mReorderingAllowed;
                    if (!canReorder) {
                        if (startIndex != recordNum) {
                            this.executeOpsTogether(records, isRecordPop, startIndex, recordNum);
                        }

                        int reorderingEnd = recordNum + 1;
                        if ((Boolean)isRecordPop.get(recordNum)) {
                            while(reorderingEnd < numRecords && (Boolean)isRecordPop.get(reorderingEnd) && !((BackStackRecord)records.get(reorderingEnd)).mReorderingAllowed) {
                                ++reorderingEnd;
                            }
                        }

                        this.executeOpsTogether(records, isRecordPop, recordNum, reorderingEnd);
                        startIndex = reorderingEnd;
                        recordNum = reorderingEnd - 1;
                    }
                }

                if (startIndex != numRecords) {
                    this.executeOpsTogether(records, isRecordPop, startIndex, numRecords);
                }

            } else {
                throw new IllegalStateException("Internal error with the back stack records");
            }
        }
    }


    private void executeOpsTogether(ArrayList<BackStackRecord> records, ArrayList<Boolean> isRecordPop, int startIndex, int endIndex) {
        boolean allowReordering = ((BackStackRecord)records.get(startIndex)).mReorderingAllowed;
        boolean addToBackStack = false;
        if (this.mTmpAddedFragments == null) {
            this.mTmpAddedFragments = new ArrayList();
        } else {
            this.mTmpAddedFragments.clear();
        }

        this.mTmpAddedFragments.addAll(this.mAdded);
        Fragment oldPrimaryNav = this.getPrimaryNavigationFragment();

        int postponeIndex;
        for(postponeIndex = startIndex; postponeIndex < endIndex; ++postponeIndex) {
            BackStackRecord record = (BackStackRecord)records.get(postponeIndex);
            boolean isPop = (Boolean)isRecordPop.get(postponeIndex);
            if (!isPop) {
                oldPrimaryNav = record.expandOps(this.mTmpAddedFragments, oldPrimaryNav);
            } else {
                oldPrimaryNav = record.trackAddedFragmentsInPop(this.mTmpAddedFragments, oldPrimaryNav);
            }

            addToBackStack = addToBackStack || record.mAddToBackStack;
        }

        this.mTmpAddedFragments.clear();
        if (!allowReordering) {
            FragmentTransition.startTransitions(this, records, isRecordPop, startIndex, endIndex, false);
        }

        executeOps(records, isRecordPop, startIndex, endIndex);// commit操作 最终执行的实际上是我们 backstackrecord 这个类里的 executeOps 方法
        postponeIndex = endIndex;
        if (allowReordering) {
            ArraySet<Fragment> addedFragments = new ArraySet();
            this.addAddedFragments(addedFragments);
            postponeIndex = this.postponePostponableTransactions(records, isRecordPop, startIndex, endIndex, addedFragments);
            this.makeRemovedFragmentsInvisible(addedFragments);
        }

        if (postponeIndex != startIndex && allowReordering) {
            FragmentTransition.startTransitions(this, records, isRecordPop, startIndex, postponeIndex, true);
            this.moveToState(this.mCurState, true);
        }

        for(int recordNum = startIndex; recordNum < endIndex; ++recordNum) {
            BackStackRecord record = (BackStackRecord)records.get(recordNum);
            boolean isPop = (Boolean)isRecordPop.get(recordNum);
            if (isPop && record.mIndex >= 0) {
                this.freeBackStackIndex(record.mIndex);
                record.mIndex = -1;
            }

            record.runOnCommitRunnables();
        }

        if (addToBackStack) {
            this.reportBackStackChanged();
        }

    }

一直到这里 我们就知道,commit 操作最终执行的实际上是我们 backstackrecord 这个类里的 executeOps 方法。

 void executeOps() {
        int numOps = this.mOps.size();

        for(int opNum = 0; opNum < numOps; ++opNum) {
            BackStackRecord.Op op = (BackStackRecord.Op)this.mOps.get(opNum);
            Fragment f = op.fragment;
            if (f != null) {
                f.setNextTransition(this.mTransition, this.mTransitionStyle);
            }

            switch(op.cmd) {
            case 1:
                f.setNextAnim(op.enterAnim);
                this.mManager.addFragment(f, false);// 根据对应的 op.cmd, fragmentManager 来管理 fragment 的一些状态。
                break;
            case 2:
            default:
                throw new IllegalArgumentException("Unknown cmd: " + op.cmd);
            case 3:
                f.setNextAnim(op.exitAnim);
                this.mManager.removeFragment(f);
                break;
            case 4:
                f.setNextAnim(op.exitAnim);
                this.mManager.hideFragment(f);
                break;
            case 5:
                f.setNextAnim(op.enterAnim);
                this.mManager.showFragment(f);
                break;
            case 6:
                f.setNextAnim(op.exitAnim);
                this.mManager.detachFragment(f);
                break;
            case 7:
                f.setNextAnim(op.enterAnim);
                this.mManager.attachFragment(f);
                break;
            case 8:
                this.mManager.setPrimaryNavigationFragment(f);
                break;
            case 9:
                this.mManager.setPrimaryNavigationFragment((Fragment)null);
            }

            if (!this.mReorderingAllowed && op.cmd != 1 && f != null) {
                this.mManager.moveFragmentToExpectedState(f);
            }
        }

       //我们也很容易就能看出来 最终都是走的 mManager.moveToState 这个方法
       //同时moveToState 也是 fragment 状态分发最重要的方法了
        if (!this.mReorderingAllowed) {
            this.mManager.moveToState(this.mManager.mCurState, true);
        }

    }

到这里应该就差不多了,最终的线索就是 只要搞明白moveToState这个函数就可以了。

     // 下面代码来自于fragment
    // 我们先去看看这个函数的参数之一new state是什么
   // 其实new state 就是代表新的状态
    static final int INITIALIZING = 0;
    static final int CREATED = 1;
    static final int ACTIVITY_CREATED = 2;
    static final int STARTED = 3;
    static final int RESUMED = 4;

下面我们可以模拟一个流程 帮助大家理解这个状态到底是干嘛的,有什么用。

比如我们先看看 fragmentactivity的源码,假设我们想看看 activity 发生 onResumne 事件的时候对 fragment 有什么影响。

    protected void onResume() {
        super.onResume();
        this.mHandler.sendEmptyMessage(2);
        this.mResumed = true;
        this.mFragments.execPendingActions();
    }

    final Handler mHandler = new Handler() {
        public void handleMessage(Message msg) {
            switch(msg.what) {
            case 2:
                FragmentActivity.this.onResumeFragments();
                FragmentActivity.this.mFragments.execPendingActions();
                break;
            default:
                super.handleMessage(msg);
            }

        }
    };

    protected void onResumeFragments() {
        this.mFragments.dispatchResume();
    }

    public void dispatchResume() {
        this.mStateSaved = false;
        this.mStopped = false;
        this.dispatchStateChange(4);
    }

    //下面的代码来自 FragmentManagerImpl
    //一直追踪到这里就能明白 activity 的声明周期与 fragment 声明周期关联的时候就是通过 moveToState 这个函数来完成。
    private void dispatchStateChange(int nextState) {
        try {
            this.mExecutingActions = true;
            this.moveToState(nextState, false);
        } finally {
            this.mExecutingActions = false;
        }

        this.execPendingActions();
    }

一直追踪到这里就能明白 activity 的声明周期与 fragment 声明周期关联的时候就是通过 moveToState 这个函数来完成

再理一下相关类的关系吧

FragmentManager 是什么 ?

FragmentActivity 中持有类 FragmentController 的一个对象 mFragments,而在 FragmentController 的 createController 方法中会传入 HostCallbacks( 其为 FragmentActivity 的一个内部类)。
而该 HostCallbacks(其为接口 FragmentHostCallback 的一个实现类) 在构造时会传入一个当前 activity(FragmentActivity)的引用。

===>

1 FragmentHostCallback 持有对 fragmentActivity,以及其对应的context和handler的引用

2 FragmentController 通过 mHost 持有对 FragmentHostCallback的引用。

而当我们调用 getSupportFragmentManager(),其实是 FragmentController 转给 FragmentHostCallback ,并调用其 getFragmentManagerImpl 方法来获取一个 FragmentManagerImpl 对象。

===>

1 所以说 FragmentManager 其实就是 FragmentManagerImpl 的对象,其为 FragmentManager 的具体实现类

BackStackRecord 是什么

当我们调用 FragmentManagerImpl 的 beginTransaction方法时,返回一个 BackStackRecord 的对象(该对象继承 FragmentTransaction,并持有对 FragmentManagerImpl 对象的引用)。
此时我们可以通过对象 backStackRecord 来将 fragmentA 添加到指定的 container 中。添加 fragmentA 本质就是__将 fragment 和对应的操作(如:add remove replace)封装成一个Op对象,然后将该对象存储在一个数组列表中__。

这里需要注意的是,containerId 为什么不存储 ?

其实 containerId 已经存储到 fragmentA 中了!!!

      // BackStackRecord执行add操作时会执行如下代码:
      fragment.mContainerId = fragment.mFragmentId = containerViewId;

backStackRecord 对象调用commit时又发生了什么呢?

上面说过,backStackRecord 对象持有对 FragmentManagerImpl 对象的引用,而commit操作,其实就回调了 FragmentManagerImpl 对象的 enqueueAction 方法来对 backStackRecord 对象进行操作。
到这里 backStackRecord 可以说暂时完成使命了。

其实 BackStackRecord 可以理解为 BackStack + Record, Record为记录的意思,记录啥呢? 其实就是我们要对fragment执行的一些操作。

那么BackStack如何理解呢 ?

FragmentManagerImpl 到底做了些啥?

我们将 BackStackRecord 对象中记录的一些对fragment的操作当做一个action。 那么当 backStackRecord 调用commit时,FragmentManagerImpl 对象如何处理这些 action 的呢?

1 用一个数组列表(PendingActions)去存储这个 action,然后 post 一个runnable(mExecCommit),到主线程去执行。

核心代码如下:

  public boolean execPendingActions() {
        this.ensureExecReady(true);

        boolean didSomething;
        for(didSomething = false; this.generateOpsForPendingActions(this.mTmpRecords, this.mTmpIsPop); didSomething = true) {
            this.mExecutingActions = true;

            try {
                this.removeRedundantOperationsAndExecute(this.mTmpRecords, this.mTmpIsPop);
            } finally {
                this.cleanupExec();
            }
        }

        this.doPendingDeferredStart();
        this.burpActive();
        return didSomething;
    }

该方法的执行,会调用到 BackStackRecord对象的 executeOps,这个方法就是根据不同的操作(所谓操作就是OP.CMD的那个值)来分发不同的事件,
从而调用 FragmentManagerImpl 来转换 fragment 生命周期的方法!

一直分析到这里,相信大家就对fragment的源码基础知识有一个不错的理解了,在这里就简单总结一下上面的分析:

  1. FragmentActivity 是具有支持 fragment 功能的最底层的 activity, 其他什么 AppCompatActivity 都是他的子类!

  2. FragmentActivity 主要负责就是生命周期的转发,比如 onCreate onResume onDestroy 等等,这就是为什么 activity 和 fragment 状态能统一的原因了!

当然了,分发的原因就是因为 fragmentActivity 对象持有一个 fragmentController 的实例!

其实讲白了,fragmentController 就是因为它自己有一个 fragmentHostCallback,然后这个 fragmentHostCallback 还持有了 fragmentManagerImpl,

最终由 fragmentManagerImpl 的 moveToState 方法完成 fragment 生命周期的转换。

  1. fragementHostCallback 持有了 activity 的很多资源,context,handler 是其中最主要的2个。fragmentManagerImpl 就是因为拿到了 activty 的这2个资源,所以才能和 activty 互相通信的!

    为什么 fragmentManagerImpl 可以拿到 activty 的 context 和 handler?

    因为其为 fragementHostCallback 的内部类

  2. fragmentMangerImple 就是 fragmentManger 的具体实现类。moveToState方法就是在这个里面实现的

  3. FragmentTransition 也是个抽象类,他主要就是提供对外的接口函数的 add replace move 这种。BackStackRecord 就是它的具体实现类,还额外实现了 OpGenerator 接口。

  4. BackStackRecord 里面会有个 executeOps() 方法。这个方法就是根据不同的操作(所谓操作就是OP.CMD的那个值)来分发不同的事件,从而调用 fragmentManager的各种转换 fragment 生命周期的方法!

猜你喜欢

转载自blog.csdn.net/XFORG1992/article/details/88606907