搞懂 Fragment 的生命周期

Fragment 的状态和回调

和 Activity 一样,Fragment 也有着自己的生命周期。

Activity 在其生命周期中有四种状态,分别是运行状态、暂停状态、停止状态和销毁状态。Fragment 也会经历这几种状态,只不过稍微有些区别。

  1. 运行状态(Resumed)

    当一个 Fragment 所关联的 Activity (宿主 Activity)处于运行状态,并且该 Fragment 对用户来说可见、可进行交互时,它就处于运行状态。

  2. 暂停状态(Paused)

    当宿主 Activity 进入暂停状态时(被透明窗口或对话框覆盖),其下的 Fragment 就会进入暂停状态。

  3. 停止状态(Stopped)

    当宿主 Activity 进入停止状态(完全不可见)时,其下的 Fragment 就会进入停止状态。或者是通过 FragmentTransaction 的 replace() 方法将 Fragment 替换了,并且将该事务添加到了返回栈时,被替换的 Fragment 也会进入停止状态,并且其视图会被销毁,这时的 Fragment 是完全不可见的。

  4. 销毁状态(Destroyed)

    当宿主 Activity 被销毁时,其下的 Fragment 就会进入销毁状态。或者通过 remove() 方法将 Fragment 移除了,并且在提交事务之前没有将事务添加到返回栈中,此时的 Fragment 实例也会进入销毁状态。

核心生命周期回调

同样地,Fragment 也和 Activity 一样,有着一系列回调方法对应着生命周期的不同阶段。

  • onAttach():Fragment 已与宿主 Activity 建立关联时调用,此时可以获取到 Context

  • onCreate():Fragment 实例被创建时调用,可以执行一些与视图无关的初始化操作。

  • onCreateView():为 Fragment 创建视图(加载布局)时调用,该方法会创建并返回 Fragment 的视图(View)。

  • onViewCreated():在 onCreateView() 返回视图之后被立即调用,我们可以执行与视图相关的初始化操作(如设置监听器)。

  • onStart():Fragment 的视图变为对用户可见。

  • onResume():Fragment 进入可交互状态。

  • onPause():Fragment 失去焦点,但仍然可见。

  • onStop():Fragment 对用户完全不可见。

  • onDestroyView():Fragment 的视图被销毁移除时调用,我们执行和视图相关的清理工作,防止内存泄漏(如不再持有对 View Binding 对象的引用)。

  • onDestroy():Fragment 实例正在被销毁,可以执行清理操作。

  • onDetach():Fragment 与宿主 Activity 解除关联时调用。

Fragment 生命周期图示

Fragment 完整的生命周期示意图:

你也可以参考官方的生命周期图,它展示了 Fragment 生命周期与其视图生命周期的分离与对应关系。

体验 Fragment 的生命周期

我们在 FragmentTest 项目的基础上进行修改,详情见于该专栏的上一篇文章,来感受一下生命周期的变化。

RightFragment 中重写各个回调,并打印日志,代码如下:

kotlin 复制代码
class RightFragment : Fragment() {

    private var _binding: RightFragmentBinding? = null
    private val binding get() = _binding!!


    companion object {
        const val TAG = "RightFragment"
    }

    override fun onAttach(context: Context) {
        super.onAttach(context)
        Log.d(TAG, "onAttach")
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        Log.d(TAG, "onCreate")
    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?,
    ): View {
        Log.d(TAG, "onCreateView")
        _binding = RightFragmentBinding.inflate(inflater, container, false)
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        Log.d(TAG, "onViewCreated")
    }

    override fun onStart() {
        super.onStart()
        Log.d(TAG, "onStart")
    }

    override fun onResume() {
        super.onResume()
        Log.d(TAG, "onResume")
    }

    override fun onPause() {
        super.onPause()
        Log.d(TAG, "onPause")
    }

    override fun onStop() {
        super.onStop()
        Log.d(TAG, "onStop")
    }

    override fun onDestroyView() {
        super.onDestroyView()
        Log.d(TAG, "onDestroyView")
        _binding = null // 在视图销毁时解除对绑定对象的引用,防止内存泄漏
    }

    override fun onDestroy() {
        super.onDestroy()
        Log.d(TAG, "onDestroy")
    }

    override fun onDetach() {
        super.onDetach()
        Log.d(TAG, "onDetach")
    }
}

运行程序,查看日志打印信息:

可以看到 RightFragment 被首次添加并显示时,会依次调用 onAttach()onCreate()onCreateView()onViewCreated()onStart()onResume() 方法。

然后点击按钮,将当前显示的 Fragment 换成 AnotherRightFragment,并且将该事务添加到返回栈,此时的日志打印信息:

此时的 RightFragment 进入了停止状态,视图被销毁了,onPause()onStop()onDestroyView() 方法被调用。但实例并没有被销毁(onDestroy()onDetach() 方法没被调用),它还在返回栈中,还是可以被恢复的。

按下返回键,RightFragment 会重新显示在界面中,打印信息如下:

因为 RightFragment 从返回栈中恢复,其视图要进行重建,所以会依次调用 onCreateView()onViewCreated()onStart()onResume() 方法,最终回到运行状态

再次按下返回键,打印信息如图所示:

会依次调用 onPause()onStop()onDestroyView()onDestroy()onDetach() 方法,彻底将 RightFragment 销毁。

状态的保存与恢复

另外当因屏幕旋转、配置变更、内存不足等原因,系统销毁并重建了 Fragment,你可以通过重写 onSaveInstanceState() 方法来保存数据,它会在被系统销毁之前调用。

kotlin 复制代码
override fun onSaveInstanceState(outState: Bundle) {
    super.onSaveInstanceState(outState)
}

你可以在 onCreate()onCreateView()onViewCreated() 方法中通过其 savedInstanceState 参数恢复数据。

或者重写 onViewStateRestored 方法,我们也可以在这里恢复数据并更新界面。

kotlin 复制代码
override fun onViewStateRestored(savedInstanceState: Bundle?) {
    super.onViewStateRestored(savedInstanceState)
}
相关推荐
ii_best1 小时前
按键精灵支持安卓14、15系统,兼容64位环境开发辅助工具
android
美狐美颜sdk1 小时前
跨平台直播美颜SDK集成实录:Android/iOS如何适配贴纸功能
android·人工智能·ios·架构·音视频·美颜sdk·第三方美颜sdk
恋猫de小郭6 小时前
Meta 宣布加入 Kotlin 基金会,将为 Kotlin 和 Android 生态提供全新支持
android·开发语言·ios·kotlin
aqi007 小时前
FFmpeg开发笔记(七十七)Android的开源音视频剪辑框架RxFFmpeg
android·ffmpeg·音视频·流媒体
androidwork9 小时前
深入解析内存抖动:定位与修复实战(Kotlin版)
android·kotlin
梦天20159 小时前
android核心技术摘要
android
szhangbiao11 小时前
“开发板”类APP如果做屏幕适配
android
高林雨露12 小时前
RecyclerView中跳转到最后一条item并确保它在可视区域内显示
android
移动开发者1号14 小时前
ReLinker优化So库加载指南
android·kotlin
山野万里__14 小时前
C++与Java内存共享技术:跨平台与跨语言实现指南
android·java·c++·笔记