搞懂 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)
}
相关推荐
小草帽学编程22 分钟前
鸿蒙Next开发真机调试签名申请流程
android·华为·harmonyos
dog shit2 小时前
web第十次课后作业--Mybatis的增删改查
android·前端·mybatis
科技道人3 小时前
Android15 launcher3
android·launcher3·android15·hotseat
CYRUS_STUDIO8 小时前
FART 脱壳某大厂 App + CodeItem 修复 dex + 反编译还原源码
android·安全·逆向
Shujie_L10 小时前
【Android基础回顾】四:ServiceManager
android
Think Spatial 空间思维11 小时前
【实施指南】Android客户端HTTPS双向认证实施指南
android·网络协议·https·ssl
louisgeek11 小时前
Git 使用 SSH 连接
android
二流小码农12 小时前
鸿蒙开发:实现一个标题栏吸顶
android·ios·harmonyos
八月林城13 小时前
echarts在uniapp中使用安卓真机运行时无法显示的问题
android·uni-app·echarts