Fragment 生命周期深度图解:从 onAttach 到 onDetach 完整流程(面试必备)
目录
- 概述
- 完整生命周期图
- 各阶段详解
- [与 Activity 生命周期对比](#与 Activity 生命周期对比)
- [Fragment 独特方法](#Fragment 独特方法)
- 常见场景分析
- 状态保存与恢复
- 实战代码示例
1. 概述
Fragment 有自己的生命周期,但完全依赖 Activity。
Activity 创建
↓
Activity 窗口创建完成
↓
Fragment 开始自己的生命周期
↓
... 运行中 ...
↓
Activity 销毁
↓
Fragment 销毁
Fragment 生命周期跟随 Activity,但有自己独特的方法。
2. 完整生命周期图
Fragment 创建
│
▼
onAttach() ────────────── Fragment 绑定到 Activity
│
▼
onCreate() ────────────── 初始化 Fragment(不创建视图)
│
▼
onCreateView() ────────── 创建 Fragment 视图(加载布局)
│
▼
onViewCreated() ───────── 视图创建完成(绑定控件、设置监听)
│
▼
onStart() ─────────────── Fragment 可见
│
▼
onResume() ────────────── Fragment 可交互
│
│◄──────── 运行中 ────────┤
│
▼
onPause() ─────────────── 失去焦点(部分可见)
│
▼
onStop() ──────────────── 完全不可见
│
▼
onDestroyView() ────────── 视图销毁(Fragment 对象还在)
│
▼
onDestroy() ───────────── Fragment 销毁
│
▼
onDetach() ────────────── 脱离 Activity
3. 各阶段详解
3.1 onAttach()
kotlin
override fun onAttach(context: Context) {
super.onAttach(context)
// context 就是绑定的 Activity
// 这里可以安全地转换:activity = context as MyActivity
}
调用时机 :Fragment 刚绑定到 Activity 时
特点 :最早被调用,此时 Fragment 和 Activity 建立了联系
用途:获取 Activity 引用(但通常在 onViewCreated 中获取更安全)
3.2 onCreate()
kotlin
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// 初始化数据、设置 retainInstance 等
}
调用时机 :Activity 的 onCreate 之后
特点 :不创建视图 ,只做初始化
注意:此时 View 为 null,不能在这里绑定控件
3.3 onCreateView()
kotlin
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_example, container, false)
}
调用时机 :需要显示 Fragment 时
特点 :创建 Fragment 的视图 (加载布局)
重要:
- 返回 null 表示不显示任何视图
container是 Fragment 将要放入的父容器savedInstanceState用于恢复状态
3.4 onViewCreated()
kotlin
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// 在这里绑定控件和设置监听
btnSubmit = view.findViewById(R.id.btnSubmit)
btnSubmit?.setOnClickListener { ... }
}
调用时机 :onCreateView 之后,视图已经创建完成
特点 :可以安全地使用 view.findViewById
用途:绑定控件、设置监听、初始化数据展示
3.5 onStart() / onResume()
kotlin
override fun onStart() {
super.onStart()
// Fragment 可见
}
override fun onResume() {
super.onResume()
// Fragment 可交互
}
| 方法 | 含义 |
|---|---|
onStart() |
Fragment 变得可见(但用户还无法交互) |
onResume() |
Fragment 可交互(获得焦点) |
注意:这两个方法通常不需要重写,控件的交互监听已足够。
3.6 onPause() / onStop()
kotlin
override fun onPause() {
super.onPause()
// 失去焦点(部分可见)或即将不可见
}
override fun onStop() {
super.onStop()
// 完全不可见
}
使用场景:
onPause():保存需要持久化的数据(如草稿)onStop():暂停动画、释放资源
3.7 onDestroyView()
kotlin
override fun onDestroyView() {
super.onDestroyView()
// 视图被销毁,但 Fragment 对象还在
// 可以在 onCreateView 中重新创建
}
重要 :这是 Fragment 生命周期中最容易混淆的点
Activity 销毁 → Fragment 的 onDestroyView() 被调用
→ 视图被销毁
→ 但 Fragment 对象还在内存中
返回栈弹出 → Fragment 的 onCreateView() 重新被调用
→ 视图重新创建
→ onViewCreated 重新被调用
3.8 onDestroy() / onDetach()
kotlin
override fun onDestroy() {
super.onDestroy()
// Fragment 真正被销毁
}
override fun onDetach() {
super.onDetach()
// Fragment 脱离 Activity
}
调用时机:
onDestroy():Fragment 被移除且不打算恢复onDetach():Fragment 完全脱离 Activity
4. 与 Activity 生命周期对比
Activity Fragment 说明
────────────────────────────────────────────────────────────────────
onCreate() → onCreate() 初始化
onAttach() 绑定到 Activity
onCreateView() 创建视图 ← 加载布局
onViewCreated() 视图创建完成 ← 绑定控件
onStart() → onStart() 可见
onResume() → onResume() 可交互
onPause() → onPause() 失去焦点
onStop() → onStop() 不可见
onDestroy() → onDestroyView() 视图销毁
onDestroy() Fragment 销毁
onDetach() 脱离 Activity
5. Fragment 独特方法
5.1 setUserVisibleHint()(已废弃)
用于 ViewPager 中判断 Fragment 是否可见。
kotlin
@Deprecated("Use setMaxLifecycle instead")
override fun setUserVisibleHint(isVisible: Boolean) {
super.setUserVisibleHint(isVisible)
if (isVisible) {
// Fragment 可见
} else {
// Fragment 不可见
}
}
5.2 setMenuVisibility()
控制 Fragment 是否显示菜单。
kotlin
override fun setMenuVisibility(menuVisible: Boolean) {
super.setMenuVisibility(menuVisible)
// menuVisible = true 时显示菜单
}
6. 常见场景分析
场景1:Fragment 初次添加
Activity onCreate()
↓
Fragment onAttach()
Fragment onCreate()
Fragment onCreateView()
Fragment onViewCreated()
Fragment onStart()
Fragment onResume()
场景2:按 Back 键返回(无返回栈)
Activity onPause()
Activity onStop()
Activity onDestroy()
↓
Fragment onPause()
Fragment onStop()
Fragment onDestroyView()
Fragment onDestroy()
Fragment onDetach()
场景3:按 Back 键返回(有返回栈)
Fragment 按下 Back
↓
Fragment onPause()
Fragment onStop()
Fragment onDestroyView() ← 视图销毁
↓
系统 pop 返回栈
↓
Fragment onCreateView() ← 视图重新创建
Fragment onViewCreated()
Fragment onStart()
Fragment onResume()
场景4:屏幕旋转(配置变更)
Activity onPause()
Activity onStop()
Activity onDestroy()
↓
Fragment onPause()
Fragment onStop()
Fragment onDestroyView()
Fragment onDestroy()
Fragment onDetach()
↓
Activity 重建...
↓
Fragment 重新创建...
7. 状态保存与恢复
7.1 onSaveInstanceState()
kotlin
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
outState.putString("name", name)
outState.putInt("count", count)
}
调用时机 :视图销毁前(onStop 之后)
用途:保存临时状态(屏幕旋转、内存不足时恢复)
7.2 在 onViewCreated 中恢复
kotlin
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// 恢复状态
savedInstanceState?.let {
name = it.getString("name", "")
count = it.getInt("count", 0)
}
}
7.3 setRetainInstance()
kotlin
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
retainInstance = true // 配置变更时保留 Fragment 实例
}
效果:屏幕旋转时,Fragment 对象不被销毁,只销毁视图
普通 Fragment:
旋转 → 对象销毁 → 重建对象 → 重建视图
setRetainInstance(true):
旋转 → 对象保留 → 只销毁视图 → 重建视图
注意:这只在 Fragment 没有加入返回栈时有效。
8. 实战代码示例
完整 Fragment 生命周期
kotlin
class ExampleFragment : Fragment() {
private var data: String = ""
override fun onAttach(context: Context) {
super.onAttach(context)
Log.d("Fragment", "onAttach")
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Log.d("Fragment", "onCreate")
// 恢复状态
savedInstanceState?.let {
data = it.getString("data", "")
}
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
Log.d("Fragment", "onCreateView")
return inflater.inflate(R.layout.fragment_example, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
Log.d("Fragment", "onViewCreated")
// 恢复状态
savedInstanceState?.let {
data = it.getString("data", "")
}
// 绑定控件
val btn = view.findViewById<Button>(R.id.btn)
btn.setOnClickListener {
data = "clicked"
}
}
override fun onStart() {
super.onStart()
Log.d("Fragment", "onStart")
}
override fun onResume() {
super.onResume()
Log.d("Fragment", "onResume")
}
override fun onPause() {
super.onPause()
Log.d("Fragment", "onPause")
}
override fun onStop() {
super.onStop()
Log.d("Fragment", "onStop")
}
override fun onSaveInstanceState(outState: Bundle) {
super.onSaveInstanceState(outState)
Log.d("Fragment", "onSaveInstanceState")
outState.putString("data", data)
}
override fun onDestroyView() {
super.onDestroyView()
Log.d("Fragment", "onDestroyView")
}
override fun onDestroy() {
super.onDestroy()
Log.d("Fragment", "onDestroy")
}
override fun onDetach() {
super.onDetach()
Log.d("Fragment", "onDetach")
}
}
总结
- Fragment 生命周期依赖 Activity,Activity 销毁时 Fragment 一定销毁
- onCreateView 是关键:加载布局,返回视图
- onViewCreated 是绑定控件的地方:视图已创建,可以安全使用 findViewById
- onDestroyView 不销毁对象:视图被销毁,但 Fragment 实例还在
- setRetainInstance(true):可以保留 Fragment 实例,只销毁视图
- 状态保存用 onSaveInstanceState:在视图销毁前保存临时数据