Fragment的故事
目次
Fragment 在原生 Android 开发中一直占有一席之地。像 ViewPager2、Dialog 都依赖 Fragment 来实现。虽然在实现底部导航(Bottom Navigation)时,ViewPager2 配合 Fragment 有一些小坑,但这并不影响 Fragment 在 Android 体系中的地位。
既然 Fragment 这么重要,就有必要深入了解它的奥秘。这篇文章就是一次探索。
联系 #
Fragment 的 add、replace、remove、show、hide 等操作,全部依赖 FragmentManager。要理解 Fragment,绕不开 FragmentManager。

上图展示了 Activity 与 FragmentManager 的关系。FragmentActivity 通过 FragmentController 来更新 Fragment 状态,也会依赖 FragmentHostCallback 来获取宿主信息(例如 Fragment 数量等)。
接下来看看 FragmentHostCallback。它其实是一个泛型类,泛型参数 <E> 一般代表宿主类型(通常是 Activity)。它本身并不对泛型做具体逻辑处理,而是充当桥梁——比如 Fragment 在获取 LayoutInflater 时需要一个 Context,这里传入的就是 Activity;Fragment 启动 Activity 的本质,也是通过宿主提供的方法来完成的。
再说大家最熟悉的 FragmentManager。
- 早期获取方式是
getFragmentManager(),对应android.app.Fragment,现已废弃。 - 现在统一推荐
getSupportFragmentManager(),来自 AndroidX 的FragmentActivity,对应androidx.fragment.app.Fragment。
所以,不是“官方只是标记废弃”,而是 AndroidX 迁移之后,旧版被弃用,新版才是维护方向。
在日常开发中,我们最常用的就是 add、replace、remove 等方法。但实际上,FragmentManager 还负责:
- 管理 Fragment 的生命周期更新
- 保存和恢复状态
- 权限请求、画中画支持
- Activity/Fragment 重建时的恢复
真正的核心远不止几个增删操作。
FragmentTransaction #
我们以一个常见的例子为起点:
| |
这里 beginTransaction() 会先创建一个 FragmentTransaction 实例。这个实例可以收集多个操作(Op),最后通过 commit 一次性提交。
add、replace、remove 等方法本质上都会封装成一个个 Op,记录操作类型和对应的 Fragment。真正执行是在调用 commit 系列方法时。
commit 系列方法 #
几个方法的区别如下:
commit() 把事务加入队列,稍后在主线程安全时异步执行。如果此时状态已经保存(比如在
onSaveInstanceState之后),会抛出异常。commitAllowingStateLoss() 与
commit()类似,但不会因为状态已保存而报错,可能导致状态丢失。commitNow() 立即执行事务,且会强制在所有挂起的异步事务之前完成。但它不允许再提交异步事务,否则会冲突。
commitNowAllowingStateLoss() 同上,只是允许在已保存状态后执行,可能造成状态丢失。
这样看下来,Fragment 的背后其实是一套完整的状态机,由 FragmentManager 统筹调度,FragmentHostCallback 作为宿主桥梁,FragmentTransaction 负责操作封装。我们日常写的一行 add(),实际上都在这套复杂机制中被逐步拆解和执行。