-
简书
-
优快云
Fragment(一)从源码角度看add和replace过程
通过这篇博客,我们能知道以下问题:
Fragmentadd()和replace()方法差别- 从源码角度分析
add()和replace()方法
1. Fragment add() 和 replace() 方法差别
add() 是添加 Fragment 到容器布局中,再搭配事务对象(FragmentTransaction)的 show() 和 hide() 方法来显示和隐藏 Fragment,replace()顾名思义“替换”,会销毁布局容器内的已有 Fragment,然后重新创建一个新的 Fragment 显示到布局容器中。通过一下两种方式的生命周期方式对比:
add-show/hide 方式生命周期:

replace 方式生命周期:

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

======================= 回退栈的使用说明 =======================
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 版本
FragmentManager 和 FragmentTransaction 的获取
FragmentActivity 中获取 FragmentManager 和 FragmentTransaction
首先看看 FragmentManager 和 FragmentTransaction 的获取
-
在
FragmentActivity中获取FragmentManagerfinal 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的变量mFragmentManager,mHost就是前面传递进来的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 中获取 FragmentManager 和 FragmentTransaction 的过程已经知道了,那么接下来看看在 Fragment 中获取 FragmentManager 和 FragmentTransaction 的过程。
Fragment 中获取 FragmentManager 和 FragmentTransaction
-
在
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,和FragmentActivity中一样,那么通过FragmentManager获取FragmentTransaction也就是相同的了,这里就不再重复了。
扩展
通过前面的了解,我们知道了 FragmentController 中的 mHost
深入解析Android Fragment的add与replace源码

本文从源码角度分析了Android Fragment的add和replace方法的区别。add方法将Fragment添加到容器中,而replace则销毁原有Fragment并新建。replace会触发完整的生命周期,而add结合hide/show只会改变Fragment的可见性。此外,文章详细探讨了从FragmentTransaction的commit到Fragment实际加载到容器中的全过程,包括关键方法的调用和操作。
最低0.47元/天 解锁文章
1367

被折叠的 条评论
为什么被折叠?



