Fragment 生命周期
每个Fragment
实例都有自己的生命周期。当用户导航并与您的应用程序交互时,您的片段会在其生命周期中的各种状态中转换,因为它们被添加、删除以及进入或退出屏幕。
要管理生命周期,请Fragment
实现 LifecycleOwner
、公开Lifecycle
您可以通过该 getLifecycle()
方法访问的对象。
每个可能的Lifecycle
状态都在 Lifecycle.State
枚举中表示。
通过Fragment
在 之上构建Lifecycle
,您可以使用可用于 处理具有生命周期感知组件的生命周期的技术和类。例如,您可以使用生命周期感知组件在屏幕上显示设备的位置。该组件可以在片段变为活动状态时自动开始侦听,并在片段移动到非活动状态时停止。
作为使用 的替代 方法LifecycleObserver
, Fragment
该类包括对应于片段生命周期中的每个更改的回调方法。其中包括 onCreate()
、 onStart()
、 onResume()
、 onPause()
、 onStop()
和 onDestroy()
。
片段的视图具有Lifecycle
独立于片段的Lifecycle
. 片段 LifecycleOwner
为其视图维护 a ,可以使用 getViewLifecycleOwner()
或 访问getViewLifecycleOwnerLiveData()
。访问视图Lifecycle
对于生命周期感知组件只应在片段视图存在时执行工作的情况很有用,例如 LiveData
仅用于在屏幕上显示的观察。
本主题详细讨论Fragment
生命周期,解释确定片段生命周期状态的一些规则,并展示Lifecycle
状态与片段生命周期回调之间的关系。
Fragment 和 Fragment 管理器
当一个片段被实例化时,它从INITIALIZED
状态开始。要让片段在其生命周期的其余部分过渡,必须将其添加到 FragmentManager
. FragmentManager
负责确定其片段应该处于什么状态,然后将它们移动到该状态。
除了片段生命周期之外,FragmentManager
还负责将片段附加到其宿主活动并在片段不再使用时将其分离。该类Fragment
有两个回调方法,onAttach()
和onDetach()
,当这些事件中的任何一个发生时,您可以覆盖它们以执行工作。
当onAttach()
片段已添加到 a FragmentManager
并附加到其宿主活动时,将调用回调。此时,片段处于活动状态,并且FragmentManager
正在管理其生命周期状态。此时,FragmentManager
诸如 findFragmentById()
返回此片段的方法。
onAttach()
总是在任何生命周期状态更改之前调用。
当onDetach()
片段已从 a 中删除FragmentManager
并与其宿主活动分离时,将调用回调。该片段不再处于活动状态,并且无法再使用 检索 findFragmentById()
。
onDetach()
在任何生命周期状态更改后始终调用。
请注意,这些回调与 FragmentTransaction
方法 attach()
和 detach()
. 有关这些方法的更多信息,请参阅 片段事务。
Fragment 生命周期状态和回调
在确定片段的生命周期状态时,FragmentManager
请考虑以下几点:
- 片段的最大状态由它的
FragmentManager
. 一个片段不能超越它的状态FragmentManager
。 - 作为 的一部分
FragmentTransaction
,您可以使用 为片段设置最大生命周期状态setMaxLifecycle()
。 - 片段的生命周期状态永远不能大于其父级。例如,父片段或活动必须在其子片段之前启动。同样,子片段必须在其父片段或活动之前停止。
向上状态转换
当通过其生命周期状态向上移动时,片段首先为其新状态调用关联的生命周期回调。一旦这个回调完成,相关 Lifecycle.Event
的将由片段的 发送给观察者Lifecycle
,然后是片段的视图Lifecycle
,如果它已被实例化。
片段已创建
当您的片段达到CREATED
状态时,它已被添加到 aFragmentManager
并且该 onAttach()
方法已被调用。
这将是通过片段的 SavedStateRegistry
. 请注意,此时 Fragment 的视图尚未创建,并且与 Fragment 的视图关联的任何状态都应仅在视图创建后才能恢复。
此转换调用 onCreate()
回调。回调还接收一个savedInstanceState
Bundle
参数,其中包含以前保存的任何状态 onSaveInstanceState()
。请注意,第一次创建片段时它savedInstanceState
有一个null
值,但对于后续重新创建它始终为非空,即使您不覆盖onSaveInstanceState()
。有关更多详细信息,请参阅 使用片段保存状态。
片段已创建并查看已初始化
Lifecycle
仅当您Fragment
提供有效View
实例时才会创建片段视图。在大多数情况下,您可以使用 带有 a的片段构造函数@LayoutId
,它会在适当的时间自动膨胀视图。您还可以覆盖 onCreateView()
以编程方式膨胀或创建片段的视图。
当且仅当您的片段视图使用非 null 实例化时 View
,该View
值设置在片段上并且可以使用 getView()
. 然后 使用 与片段视图对应getViewLifecycleOwnerLiveData()
的新内容进行更新 。INITIALIZED
LifecycleOwner
此时 onViewCreated()
也会调用生命周期回调。
这是设置视图初始状态、开始观察其回调更新片段视图的实例以及在片段视图中的任何一个或多个 实例LiveData
上设置适配器 的合适位置。RecyclerView
ViewPager2
片段和视图已创建
在片段的视图被创建后,之前的视图状态(如果有的话)会被恢复,然后视图的状态Lifecycle
会被移动到该 CREATED
状态中。视图生命周期所有者也将 ON_CREATE
事件发送给它的观察者。在这里,您应该恢复与片段视图关联的任何其他状态。
此转换还调用 onViewStateRestored()
回调。
片段和视图开始
强烈建议将 生命周期感知组件绑定到STARTED
片段的状态,因为这种状态保证片段的视图是可用的(如果已创建),并且在片段FragmentTransaction
的子节点上执行 a 是安全FragmentManager
的。如果片段的视图不为空,则片段的视图Lifecycle
会在片段移至 后STARTED
立即 Lifecycle
移至STARTED
。
当片段变为 时STARTED
,将 onStart()
调用回调。
片段和视图已恢复
当片段可见时,所有 Animator
和 Transition
效果都已完成,并且片段已准备好进行用户交互。片段 Lifecycle
移动到RESUMED
状态,并 onResume()
调用回调。
过渡到RESUMED
是指示用户现在能够与您的片段交互的适当信号。不RESUMED
应该手动设置其视图的焦点或尝试处理输入法可见性的片段。
向下状态转换
当片段向下移动到较低的生命周期状态时,片段的视图(如果已实例化)将相关Lifecycle.Event
信息发送给观察者,然后是片段的. 片段的生命周期事件发出后,片段会调用关联的生命周期回调。Lifecycle``Lifecycle
片段和视图开始
当用户开始离开片段时,当片段仍然可见时,Lifecycle
片段及其视图的 s 将移回STARTED
状态并将 ON_PAUSE
事件发送给观察者。然后片段调用它的 onPause()
回调。
片段和视图已创建
一旦片段不再可见,Lifecycle
片段及其视图的 s 将移动到CREATED
状态并将 ON_STOP
事件发送给它们的观察者。这种状态转换不仅由停止的父活动或片段触发,而且由父活动或片段保存状态触发。此行为保证在ON_STOP
保存片段状态之前调用事件。这使得事件成为可以安全地对 childON_STOP
执行 a 的最后一点 。FragmentTransaction``FragmentManager
片段已创建,视图已销毁
在所有的退出 动画和转换完成后,片段的视图已经从窗口中分离出来,片段的视图Lifecycle
被移动到DESTROYED
状态并将ON_DESTROY
事件发送给它的观察者。然后片段调用它的 onDestroyView()
回调。此时,fragment 的视图已到达其生命周期的末尾并 getViewLifecycleOwnerLiveData()
返回一个null
值。
此时,所有对片段视图的引用都应该被删除,从而允许对片段视图进行垃圾回收。
片段被破坏
如果 Fragment 被移除,或者 FragmentFragmentManager
被销毁,则 FragmentLifecycle
将进入DESTROYED
状态并将 ON_DESTROY
事件发送给它的观察者。然后片段调用它的 onDestroy()
回调。此时,片段已达到其生命周期的终点。