Fragment(一)从源码角度看add和replace过程

Fragment(一)从源码角度看add和replace过程

博客对应的Demo地址:GitHubGitee

通过这篇博客,我们能知道以下问题:

  • Fragment add()replace() 方法差别
  • 从源码角度分析 add()replace() 方法

1. Fragment add()replace() 方法差别

add() 是添加 Fragment 到容器布局中,再搭配事务对象(FragmentTransaction)的 show()hide() 方法来显示和隐藏 Fragmentreplace()顾名思义“替换”,会销毁布局容器内的已有 Fragment,然后重新创建一个新的 Fragment 显示到布局容器中。通过一下两种方式的生命周期方式对比:

add-show/hide 方式生命周期:
1-1
replace 方式生命周期:
1-2

我们可以发现,replace() 方式替换的,被替换的Fragment会被彻底销毁,新的会重新创建,每一次的加载到界面到从界面消失的过程都是一个完整的生命周期;而 add() 结合 show()/hide() 方式的Fragment,切换时并不会彻底销毁 Fragment,而是走了 onHiddenChanged() 回调方法,改变了对用户的可见性,同时注意,这个方法并不是生命周期方法。他是在FragmentTransaction调用 show()hide() 方法时才会回调的方法。

注意:如果将Fragment加入回退栈

  • 对于add方式,生命周期方法回调无影响

  • 对于 replace 方式,那么他在被替换的时候是不会走销毁的方法的,它的生命周期方法如下:
    1-3

    ======================= 回退栈的使用说明 =======================

      private fun changeShowFragment(showFragment: Fragment) {
          supportFragmentManager.beginTransaction()
              .replace(R.id.fl_content, showFragment)
      		// 将Fragment增加到回退栈,并指定回退栈的名称为 replaceFragment
              .addToBackStack("replaceFragment")
              .commitAllowingStateLoss()
      }
    
      // 重写返回按钮
      override fun handlerOnBack() {
      	// 判断回退栈是否有未出栈的Fragment
          if(supportFragmentManager.backStackEntryCount > 1){
              supportFragmentManager.popBackStack()
          }else {
              super.handlerOnBack()
          }
      }
    

    ======================= 回退栈的使用说明 结束 =======================

2. 从源码角度分析 add()replace() 方法

上面从打印结果知道了 add()replace() 的差别,这一小节,我们从源码的角度来分析、查看系统对各个方法的调用过程。

说明:源码版本是 AndroidX库,具体 androidx.fragment:1.3.4 版本

FragmentManagerFragmentTransaction 的获取

FragmentActivity 中获取 FragmentManagerFragmentTransaction

首先看看 FragmentManagerFragmentTransaction 的获取

  • FragmentActivity 中获取 FragmentManager

      final FragmentController mFragments = FragmentController.createController(new HostCallbacks());
    
      @NonNull
      public FragmentManager getSupportFragmentManager() {
          return mFragments.getSupportFragmentManager();
      }
    

    通过 mFragments 获取, mFragments 就是 FragmentController,也是 FragmentActivity 的一个成员变量,通过静态方法创建,并且传递了 HostCallbacks 对象(注意:HostCallbacks extends FragmentHostCallback,HostCallbacks继承至FragmentHostCallback),这个对象就是后面会使用到的 mHost。具体创建过程如下:

      @NonNull
      public static FragmentController createController(@NonNull FragmentHostCallback<?> callbacks) {
          return new FragmentController(checkNotNull(callbacks, "callbacks == null"));
      }
    
      // 构造私有,通过静态方法创建,并且为 mHost 赋值
      private FragmentController(FragmentHostCallback<?> callbacks) {
          mHost = callbacks;
      }
    

    FragmentActivity中调用 getSupportFragmentManager() 方法,具体是调用 mFragments.getSupportFragmentManager() 方法。所以我们看一下 FragmentController (上面说过了 mFragments 就是 FragmentController)的 getSupportFragmentManager() 方法:

      @NonNull
      public FragmentManager getSupportFragmentManager() {
          return mHost.mFragmentManager;
      }
    

    直接取的是 mHost的变量 mFragmentManagermHost 就是前面传递进来的 HostCallbacks 对象,那么我们看看这个变量是什么:

      final FragmentManager mFragmentManager = new FragmentManagerImpl();
    

    这个变量实际上是在 FragmentHostCallback 定义的,前面我们说过 HostCallbacks 继承至 FragmentHostCallback ,取到 FragmentHostCallback 类中是没有问题的。看名字应该是一个 FragmentManager 的实现类。具体定义如下:

      class FragmentManagerImpl extends FragmentManager {
      }
    

    没错,确实是继承 FragmentManager ,但是类中没有任何具体的方法,FragmentManager 本身是抽象的,不能创建对象,所以通过一个实现类来创建实例。

  • FragmentActivity 中获取 FragmentTransaction
    通过以上分析,我们知道了在Activity中获取到的 FragmentManager 就是 FragmentManagerImpl 对象,那么我们在来看看 FragmentTransaction 是怎样取的,他是通过 FragmentManager 取的,也就是 FragmentManagerImpl 对象调用beginTransaction() 方法的返回值,通过前面我们知道这个方法实际上是在 FragmentManager 实现的,所以看看 FragmentManager 中的 beginTransaction() 方法:

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

    很简单,直接创建了一个 BackStackRecord 对象返回,看看 BackStackRecord 类的定义:

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

到了这里,FragmentActivity 中获取 FragmentManagerFragmentTransaction 的过程已经知道了,那么接下来看看在 Fragment 中获取 FragmentManagerFragmentTransaction 的过程。

Fragment 中获取 FragmentManagerFragmentTransaction
  • Fragment 中获取 FragmentManager
    Fragment 中获取 FragmentManager,是通过 getChildFragmentManager() 方法,看一下 Fragment 中这个方法的定义:

      @NonNull
      final public FragmentManager getChildFragmentManager() {
          if (mHost == null) {
              throw new IllegalStateException("Fragment " + this + " has not been attached yet.");
          }
          return mChildFragmentManager;
      }
    

    直接返回了 mChildFragmentManager 对象,看看这个对象的定义:

      FragmentManager mChildFragmentManager = new FragmentManagerImpl();
    

    直接创建了 FragmentManagerImpl 对象,赋值给父类 FragmentManager,这个类我们前面已经说过了。

  • Fragment 中获取 FragmentTransaction
    既然FragmentManager对象是 FragmentManagerImpl ,和 FragmentAc

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值