Fragment系列之Fragment管理源码简介

简介:
作为一个android开发者,UI架构设计、开发肯定是必备技能,至少android应用开发还没Web端开发分的那么细,前端/后端/数据库,android从UI到数据存储都在客户端完成,而Fragment作为系统提供的页面级别的组件类,在构建复杂的页面布局和页面功能复用上有着很重要的地位,它和Activity一样有生命周期,当然就会有一个对Fragment管理类FragmentManager,这篇的目标主要对Fragment的生命周期以及Fragment是如何被管理的去解读源码,从而解答开发中Fragment常见的一些问题。

 

1. 主要涉及的类及文件

FragmentManager.java

+ FragmentManager.class

+ FragmentManagerImpl.class

BackStackRecord.java

FragmentHostCallback.java

FragmentTransaction.java

 

2. Fragment基本使用

用过Fragment的童鞋应该清楚FragmentManager对Fragment的操作有以下几类行为:

add/remove、replace、hide/show、detach/attach。

当添加或展示一个fragment时,需要通过add或replace的方式将fragment绑定到一个containerId上,简单的描述一下代码流程:

先获取到当前activity或fragment的fragmentmanager;

然后通过FragmentManager#beginTransaction()获取到FragmentTransaction对象(其实就是BackstackRecord对象);

接着通过FragmentTransaction对象通过add或replace的方式将需要展示的fragment添加进来,然后show()展示fragment。

 

3. FragmentManager的获取方式

一般在activity中直接通过getFragmentManager或getSupportFragmentManager来获取,在Fragment中通过getChildFragmentManager或getSupportChildFragmentManager来获取。

那这两种获取的方式有和区别?获取到的FragmentManager之间是否有联系呢?

先来看看Activity中getFragmentManager方法:

/**

     * Return the FragmentManager for interacting with fragments associated

     * with this activity.

     */

    public FragmentManager getFragmentManager() {

        return mFragments.getFragmentManager();

    }

 

  

   那mFragments又是什么对象呢?

在activity的成员变量定义的地方可以看到mFragments:

final FragmentController mFragments = FragmentController

.createController(new HostCallbacks());
原来时FragmentController对象,这里暂时先不看这个类。

那Fragment中的getChildFragmentManager又是如何定义的呢?

/**

     * Return the FragmentManager for interacting with fragments associated

     * with this fragment's activity.  Note that this will be non-null slightly

     * before {@link #getActivity()}, during the time from when the fragment is

     * placed in a {@link FragmentTransaction} until it is committed and

     * attached to its activity.

     *

     * <p>If this Fragment is a child of another Fragment, the FragmentManager

     * returned here will be the parent's {@link #getChildFragmentManager()}.

     */

    final public FragmentManager getFragmentManager() {

        return mFragmentManager;

    }

 

    /**

     * Return a private FragmentManager for placing and managing Fragments

     * inside of this Fragment.

     */

    final public FragmentManager getChildFragmentManager() {

        if (mChildFragmentManager == null) {

            instantiateChildFragmentManager();

            if (mState >= RESUMED) {

                mChildFragmentManager.dispatchResume();

            } else if (mState >= STARTED) {

                mChildFragmentManager.dispatchStart();

            } else if (mState >= ACTIVITY_CREATED) {

                mChildFragmentManager.dispatchActivityCreated();

            } else if (mState >= CREATED) {

                mChildFragmentManager.dispatchCreate();

            }

        }

        return mChildFragmentManager;

    }

 

可以看到实例化childFragmentManager的地方在instantiateChildFragmentManager()这个方法中:

void instantiateChildFragmentManager() {

        mChildFragmentManager = new FragmentManagerImpl();

        mChildFragmentManager.attachController(mHost, new FragmentContainer() {

            @Override

            @Nullable

            public View onFindViewById(int id) {

                if (mView == null) {

                    throw new IllegalStateException("Fragment does not have a view");

                }

                return mView.findViewById(id);

            }

 

            @Override

            public boolean onHasView() {

                return (mView != null);

            }

        }, this);

    }

原来在fragment中直接实例化了一个新的fragmentManager对象,但注意一下attachController方法,其中参数mHost是指fragment所附加到的activity对象,等下面讲解FragmentManager对象时在做介绍。

上面的getChildFragmentManager代码框中其实还有一个方法getFragmentManager,用于获取activity的fragmentmanager对象的,那是如何获取的呢?如果一个fragment嵌套fragment,那么这个activity的fragmentmanager对象又是如何传递下去的呢?

其实是跳过调用fragment# instantiate方法通过mHost对象类给当前fragment的mFragmentManager赋值的,所以当前fragment也就可以获取到Activity的fragmentmanager了,关于mHost对象以及fragment和activity之间的关联关系是如何建立的在下一节讲解。

4. FragmentManager类

现在开始对FragmentManager类做一个大致的了解,了解其作用以及如何对fragment进行管理的。首先看一下类的定义,FragmentManager是一个抽象类,在其同文件下有一个实现类FragmentManagerImpl,那就直接看impl类即可。

从fragment基本使用来看,获取到FragmentManager之后便开始事务,那看一下beginTransaction()方法的定义:

FragmentManager:

/**

     * Start a series of edit operations on the Fragments associated with

     * this FragmentManager.

     *

     * <p>Note: A fragment transaction can only be created/committed prior

     * to an activity saving its state.  If you try to commit a transaction

     * after {@link FragmentActivity#onSaveInstanceState FragmentActivity.onSaveInstanceState()}

     * (and prior to a following {@link FragmentActivity#onStart FragmentActivity.onStart}

     * or {@link FragmentActivity#onResume FragmentActivity.onResume()}, you will get an error.

     * This is because the framework takes care of saving your current fragments

     * in the state, and if changes are made after the state is saved then they

     * will be lost.</p>

     */

    public abstract FragmentTransaction beginTransaction();
 

FragmentManagerImpl:

 

@Override

public FragmentTransaction beginTransaction() {

        return new BackStackRecord(this);

    }

  可以看到impl中直接实例化了一个BackStackRecord对象。那接着后面的add、replace、show/hide等动作就是BackStackRecord对象上执行的。那FragmentManager的作用就这么多了吗?当然不是,里面还有一个比较重要的方法moveToState(),根据fragment的状态来对fragment的属性进行赋值等。具体请看FragmentManager一章。

 

5. BackstackRecord相关的操作

在BackStackRecord.java类中,定义了两个类:BackStackState和BackStackReocrd。

BackStackState实现了Parcelable接口,说明是可以被序列化的,并且可以实例化一个BackStackReocrd对象,这相当于BackStackRecord也是可以序列化传输的。

BackStackRecord继承制FragmentTransaction并实现了Runnable,内部定义了Op对象,Op是一个双向链表结构,用于保存BackStackRecord的所有操作以及对用的Fragment。在BackStackRecord的内部成员变量中保存了Op的head和tail对象,刚创建的BackStackRecord的head和tail指向同一位置,当BackStackRecord调用不同的操作方法时,tail会指向最后一个操作对象,并且每一个op对象的前后对象都是相关联的。

BackStackRecord的作用时记录一次Transaction的提交中所有的操作,保存操作的命令和对应的fragment,在正向操作时会根据Op的顺序,对op命令执行对应的FM对fragment的操作。在反向操作时,根据Op的顺序对命令执行相反的FM操作。

BackStackRecord和FragmentManager的相互关系时耦合的,两者相互依赖但分工明确,

BackStackRecord的主要职责就是记录操作状态,FragmentManager是对Fragment操作者。

 

下面简单说明一下Fragment的操作流程:

先获取到FragmentManager->beginTransaction获取到BackStackRecord对象;

->调用transaction的接口操作方法添加、删除、显示、隐藏等并保存相关操作;

->调用transaction的commit方法;

->BackStackRecord调用FragmentManager. enqueueAction方法,并将当前BackStackRecord对象作为参数传递;

->调用FragmentManager的handler发送mExecCommit消息;

->最后执行的是FragmentManager#execPendingActions;

->然后循环执行pendingActions中所有的BackStackRecord的run方法

->BackStackRecord在run方法中根据Op的操作对象的cmd又会调用对用的FM的方法,在FM的moveToState方法中会调用Fragment的对应的生命周期函数。

 

  1. 总结:

以上只是对Fragment相关类做一个简短的说明介绍,其实FragmentManager和BackStackRecord对象内部实现还是比较复杂的,在后面文章中会对其具体的细节详细介绍。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值