-
简书
-
CSDN
Fragment(一)从源码角度看add和replace过程
通过这篇博客,我们能知道以下问题:
Fragment
add()
和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
中获取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
的变量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
,和FragmentAc