一、Fragment 生命周期框架
Fragment 生命周期包含两个相互关联但又独立的周期:
- Fragment 实例生命周期 - 控制 Fragment 对象本身
- 视图生命周期 - 控制 Fragment 的 UI 组件
// Fragment 生命周期完整流程
onAttach()
↓
onCreate()
↓
onCreateView() ←─ 视图生命周期开始
↓
onViewCreated()
↓
onActivityCreated() // Deprecated in API 28
↓
onStart()
↓
onResume()
↓ // 用户交互中
onPause()
↓
onStop()
↓
onDestroyView() ←─ 视图生命周期结束
↓
onDestroy()
↓
onDetach()二、生命周期方法详解
1. 实例绑定与初始化
onAttach(Context)
override fun onAttach(context: Context) {
super.onAttach(context)
// Fragment 与宿主 Activity 建立关联
// 此时可以安全地获取 Activity 引用
val activity = requireActivity()
}- 在 Fragment 与 Activity 建立关联时调用
- 获取 Context 引用,用于后续的资源访问
- 此时 Fragment 被添加到 FragmentManager
onCreate(Bundle?)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// 初始化非 UI 相关的组件
// 恢复保存的状态
val savedData = savedInstanceState?.getString("key")
}- Fragment 实例初始化
- 执行数据恢复和初始化逻辑
- 适合初始化 ViewModel、数据源等
- 此时视图尚未创建
2. 视图创建与管理
onCreateView() - 核心视图创建方法
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// 创建并返回 Fragment 的视图层级
// container 是 Fragment 的父容器(通常为 FrameLayout)
// false 表示不立即添加到容器
return inflater.inflate(R.layout.fragment_layout, container, false)
}- 负责创建 Fragment 的 UI
- 必须返回 View 对象或 null(无 UI)
- 多次调用:配置变更、导航返回时
onViewCreated() - 视图初始化完成
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// 视图创建完成,可以安全访问 UI 组件
val textView = view.findViewById<TextView>(R.id.text_view)
textView.text = "Hello Fragment"
}- 视图层级已完全创建
- 执行视图相关的初始化逻辑
- 设置监听器、配置 Adapter 等
onActivityCreated() (已废弃)
- 在 API 28 及以上废弃
- 原本用于确保 Activity 视图创建完成
- 现使用
onViewCreated()替代
简单说明
class MyFragment : Fragment() {
private lateinit var textView: TextView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// 1. 此时还没有视图,不能操作UI
// 可以初始化数据
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?): View {
// 2. 创建视图,但不添加到container
val view = inflater.inflate(R.layout.fragment_layout, container, false)
return view
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// 3. 视图已创建,可以安全地查找和操作
textView = view.findViewById(R.id.text_view)
textView.text = "Hello Fragment"
}
}Q:Fragment的onCreateView()类似于Activity的setContentView()吗?
A:不是的,这里有一个重要的概念区别。Fragment 要比 Activity 灵活很多,Fragment 不是内容,而是内容的容器和管理器。负责:管理一组 UI 组件(按钮、列表、文本等);处理这些 UI 的生命周期;响应用户交互;管理状态。
- Fragment = 控制器 + 生命周期管理器
- Fragment 的视图 = 实际显示的内容
Fragment 可以重新创建它的视图,而 Fragment 实例本身保持不变
场景1:Fragment A → Fragment B → 返回 Fragment A
时间线:
1. 打开 Fragment A
- Fragment A onCreate() ← 一次
- Fragment A onCreateView() ← 第一次
2. 导航到 Fragment B
- Fragment A onDestroyView() ← 视图销毁,实例还在
- Fragment B onCreate()
- Fragment B onCreateView()
3. 按返回键回到 Fragment A
- Fragment B 销毁
- Fragment A onCreateView() ← 第二次!重新创建视图// 场景:Fragment 在返回栈中,用户按返回键回到这个 Fragment
class MyFragment : Fragment() {
private var count = 0 // 实例变量,Fragment 存在就一直存在
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// 这里只在 Fragment 创建时调用一次
Log.d("Lifecycle", "onCreate called")
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?): View {
count++
Log.d("Lifecycle", "onCreateView called 第${count}次")
// 每次返回这个 Fragment 时,都会重新创建视图
return inflater.inflate(R.layout.my_fragment, container, false)
}
}Q:FragmentA → FragmentB,实例销毁吗?
A:看情况!取决于你是否添加到返回栈
// 情况1:添加到返回栈 → 实例不销毁,只销毁视图
supportFragmentManager.beginTransaction()
.replace(R.id.container, FragmentB())
.addToBackStack("fragmentA") // 关键:添加到返回栈
.commit()
// 生命周期:
// FragmentA: onPause() → onStop() → onDestroyView()
// 实例保留,视图销毁
// 情况2:不添加到返回栈 → 实例销毁
supportFragmentManager.beginTransaction()
.replace(R.id.container, FragmentB())
// 不调用 addToBackStack
.commit()
// 生命周期:
// FragmentA: onPause() → onStop() → onDestroyView() → onDestroy() → onDetach()
// 实例和视图都销毁Q:Fragment 返回栈到底是什么?
Fragment 返回栈 = 操作记录的回滚栈。栈里存的不是 Fragment 实例,而是操作记录!
// 示例流程:
// 第1步:添加 FragmentA
supportFragmentManager.beginTransaction()
.add(R.id.container, FragmentA())
.addToBackStack("addA") // 记录"添加A"的操作
.commit()
// 栈内容:[添加FragmentA]
// 第2步:替换为 FragmentB
supportFragmentManager.beginTransaction()
.replace(R.id.container, FragmentB())
.addToBackStack("replaceWithB") // 记录"用B替换"的操作
.commit()
// 栈内容:[添加FragmentA] ← [用B替换] ← 栈顶
// 当前显示:FragmentB
// 第3步:用户按返回键
// 系统:弹出栈顶记录 [用B替换]
// 执行反向操作:移除B,恢复A
// 当前显示:FragmentA
// 栈内容:[添加FragmentA]Q:addToBackStack 是干什么的?
Q:Activity 的栈和 Fragment 的返回栈什么区别?
完全不同!这是关键区别
// Activity 栈(系统管理,每个应用一个)
// 启动 ActivityB:
startActivity(Intent(this, ActivityB::class.java))
// 栈状态:
// 栈底:[ActivityA] → [ActivityB] ← 栈顶(当前显示)
// 按返回键:ActivityB finish(),显示 ActivityA// Fragment 返回栈(每个 Activity 都有自己的 Fragment 返回栈)
// 显示 FragmentB(添加到返回栈):
supportFragmentManager.beginTransaction()
.replace(R.id.container, FragmentB())
.addToBackStack("fragmentA")
.commit()
// 栈状态:
// Activity 的 FragmentManager 内部有一个栈
// 栈顶:FragmentB 的显示操作
// 栈底:FragmentA 的初始添加操作
// 按返回键:弹出栈顶操作(回到 FragmentA)3. 可见性状态管理
onStart()
override fun onStart() {
super.onStart()
// Fragment 对用户可见
// 适合执行需要与 UI 同步的初始化
}onResume()
override fun onResume() {
super.onResume()
// Fragment 可交互
// 恢复动画、传感器、摄像头等
}onPause()
override fun onPause() {
super.onPause()
// Fragment 失去交互焦点
// 保存临时数据,暂停耗时操作
}onStop()
override fun onStop() {
super.onStop()
// Fragment 完全不可见
// 释放 UI 相关资源
}4. 销毁阶段
onDestroyView() - 关键分离点
override fun onDestroyView() {
super.onDestroyView()
// Fragment 视图被移除
// 但 Fragment 实例可能仍存在
// 必须在此清理所有视图引用
}- 核心特性:Fragment 可以独立于视图存在
- 调用场景:
- Fragment 被替换但保留在返回栈
- 配置变更(旋转屏幕)
- Activity 重建
onDestroy()
override fun onDestroy() {
super.onDestroy()
// Fragment 实例即将销毁
// 清理所有资源
}onDetach()
override fun onDetach() {
super.onDetach()
// Fragment 与 Activity 断开连接
// 不能再访问 Activity 引用
}三、生命周期状态迁移
状态迁移场景分析
场景1:Fragment 替换(A → B)
Fragment A:
onPause() → onStop() → onDestroyView()
// 实例保留在内存中
Fragment B:
onCreate() → onCreateView() → onViewCreated() →
onStart() → onResume()场景2:配置变更(屏幕旋转)
// 旧实例销毁
onPause() → onStop() → onDestroyView() →
onDestroy() → onDetach()
// 新实例创建
onAttach() → onCreate() → onCreateView() →
onViewCreated() → onStart() → onResume()场景3:添加到返回栈
// 将 Fragment 添加到返回栈
fragmentTransaction.replace(R.id.container, fragment)
fragmentTransaction.addToBackStack("tag")
fragmentTransaction.commit()
// 此时生命周期
onPause() → onStop() → onDestroyView()
// 实例保留四、关键概念:视图与实例的分离
Fragment 的状态矩阵
| 状态 | 实例存在 | 视图存在 | 可见 | 可交互 |
|---|---|---|---|---|
| 活跃 | ✓ | ✓ | ✓ | ✓ |
| 暂停 | ✓ | ✓ | ✓ | ✗ |
| 停止 | ✓ | ✓ | ✗ | ✗ |
| 视图销毁 | ✓ | ✗ | ✗ | ✗ |
| 完全销毁 | ✗ | ✗ | ✗ | ✗ |
视图销毁但实例存活的场景
- 返回栈导航
// Fragment 进入返回栈时
supportFragmentManager.beginTransaction()
.replace(R.id.container, fragmentB)
.addToBackStack(null) // FragmentA 进入返回栈
.commit()
// FragmentA: 视图销毁,实例保留- ViewPager 中的非当前页
// ViewPager 只保持相邻 Fragment 的视图
// 非当前页的 Fragment 视图被销毁
viewPager.adapter = FragmentPagerAdapter(
listOf(fragment1, fragment2, fragment3)
)
// fragment2 当前显示,fragment1 和 fragment3 视图可能被销毁- 配置变更处理
// 在 onCreate() 中检查 savedInstanceState
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (savedInstanceState != null) {
// 配置变更重建,之前的状态已保存
}
}五、生命周期感知的数据管理
1. 数据初始化时机
class DataFragment : Fragment() {
// 1. 非 UI 数据:在 onCreate 初始化
private lateinit var repository: DataRepository
// 2. UI 相关数据:在 onViewCreated 初始化
private lateinit var adapter: RecyclerViewAdapter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
repository = DataRepository() // 非 UI 初始化
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
adapter = RecyclerViewAdapter() // UI 相关初始化
}
}2. 状态保存与恢复
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
// 保存状态到 Bundle
outState.putString("key", importantData)
}
override fun onViewStateRestored(savedInstanceState: Bundle?) {
super.onViewStateRestored(savedInstanceState)
// 恢复状态
importantData = savedInstanceState?.getString("key")
}3. 视图生命周期感知的观察者
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// 使用 viewLifecycleOwner 确保观察者随视图销毁而清理
viewModel.liveData.observe(viewLifecycleOwner) { data ->
updateUI(data)
}
}六、实践模式与常见问题
正确模式:分离实例与视图逻辑
class ProperFragment : Fragment() {
// 实例级别数据
private val viewModel: MyViewModel by viewModels()
private lateinit var dataSource: DataSource
// 视图级别数据
private var recyclerView: RecyclerView? = null
private var adapter: MyAdapter? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// 初始化实例数据
dataSource = DataSource(requireContext())
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?): View {
return inflater.inflate(R.layout.fragment_proper, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// 初始化视图组件
recyclerView = view.findViewById(R.id.recycler_view)
adapter = MyAdapter()
recyclerView?.adapter = adapter
}
override fun onDestroyView() {
// 清理视图引用
recyclerView?.adapter = null
recyclerView = null
adapter = null
super.onDestroyView()
}
override fun onDestroy() {
// 清理实例数据
dataSource.close()
super.onDestroy()
}
}常见错误模式
class LeakyFragment : Fragment() {
// 错误:持有视图引用但未在 onDestroyView 中清理
private lateinit var heavyView: HeavyCustomView
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
heavyView = view.findViewById(R.id.heavy_view)
heavyView.startAnimation() // 持有强引用
}
// 缺少 onDestroyView() 清理
// 当 Fragment 进入返回栈时:
// - heavyView 持有已销毁视图的引用
// - 内存泄漏!
}七、生命周期流程图解
创建流程:
onAttach() ← 绑定到 Activity
↓
onCreate() ← 实例初始化
↓
onCreateView() ← 创建视图
↓
onViewCreated() ← 视图初始化
↓
onStart() ← 可见
↓
onResume() ← 可交互
销毁流程:
onPause() ← 失去交互
↓
onStop() ← 不可见
↓
onDestroyView() ← 视图销毁 ← 关键点!
↓
onDestroy() ← 实例销毁
↓
onDetach() ← 解除绑定八、核心要点总结
- Fragment 生命周期包含两个层级:实例生命周期和视图生命周期
onDestroyView()是分离点:Fragment 可以在没有视图的情况下存在- 视图引用必须在
onDestroyView()中清理:避免内存泄漏 - 配置变更会触发完整重建:通过 savedInstanceState 保持状态
- 返回栈中的 Fragment 保留实例但销毁视图:理解这种半销毁状态
- 使用
viewLifecycleOwner管理 UI 相关操作:自动处理生命周期
这种设计让 Fragment 能够灵活地适应动态 UI 组合、配置变更和导航场景,是现代 Android 架构的基石。
更新: 2026-01-15 17:47:51
原文: https://www.yuque.com/dongpozhouzi-mshe3/zhm85g/lp8bgkug8gknk7f4