Fragment 生命周期深度图解:从 onAttach 到 onDetach 完整流程(面试必备)

Fragment 生命周期深度图解:从 onAttach 到 onDetach 完整流程(面试必备)


目录

  1. 概述
  2. 完整生命周期图
  3. 各阶段详解
  4. [与 Activity 生命周期对比](#与 Activity 生命周期对比)
  5. [Fragment 独特方法](#Fragment 独特方法)
  6. 常见场景分析
  7. 状态保存与恢复
  8. 实战代码示例

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")
    }
}

总结

  1. Fragment 生命周期依赖 Activity,Activity 销毁时 Fragment 一定销毁
  2. onCreateView 是关键:加载布局,返回视图
  3. onViewCreated 是绑定控件的地方:视图已创建,可以安全使用 findViewById
  4. onDestroyView 不销毁对象:视图被销毁,但 Fragment 实例还在
  5. setRetainInstance(true):可以保留 Fragment 实例,只销毁视图
  6. 状态保存用 onSaveInstanceState:在视图销毁前保存临时数据
相关推荐
众少成多积小致巨1 小时前
Android 源码查看笔记
android·源码
红星照耀华夏1 小时前
模拟面试系列-ClassLoader
面试·职场和发展
knight_9___2 小时前
Agent开发面试圣经8
面试·职场和发展
angerdream2 小时前
Android手把手编写儿童手机远程监控App之前台服务
android
银色火焰战车2 小时前
浅析golang中的垃圾回收机制(GC)
java·jvm·golang
zhangjw342 小时前
第4篇:Java数组与字符串:从基础用法到面试高频考点
java·java基础知识
俺爱吃萝卜2 小时前
Spring Boot 3 + JDK 17:新一代微服务架构最佳实践
java·spring boot·架构
曹牧2 小时前
Spring :component-scan
java·后端·spring
王二端茶倒水2 小时前
现在AI Agent 已经能够代替程序员的工作了,作为一个程序员的我该如何规划以后的职业,请认真思考后给我最靠谱可行的建议。
前端·后端·面试