Jetpack 生命周期:Fragment 的视图生命周期永远不会达到 CREATED 状态,永远不会被销毁

问题描述 投票:0回答:1

问题

我最近注意到一个案例,在一个 Android 应用程序中,触发了以下异常:

java.lang.IllegalArgumentException: Cannot add the same observer with different lifecycles

在片段的

onViewCreated
回调(比如片段A)中为视图模型的实时数据注册一些观察者时发生:

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    ...
    myViewModel.myLiveData.observe(viewLifecycleOwner, Observer(::onValueChanged))
    ...
}

这让我想到这发生在一种特定情况下,当在活动的

onCreate
中收到意图并决定导航到另一个片段(比如片段B)时。

override fun onCreate(savedInstanceState: Bundle?) {
    if ("myAction" == intent?.action) {
        if (R.id.fragmentA == navController.currentDestination?.id) {
            navController.navigate(FragmentADirections.actionFragmentAToFragmentB())
        }
    }
}

如果用户从片段 B 导航回片段 A,则抛出

IllegalArgumentException

调查

在记录生命周期方面发生的事情后,我意识到片段 A 的

viewLifecycleOwner
的生命周期状态是
INITIALIZED
当片段为 LiveData 注册观察者时。 这符合文档推荐的内容

... getViewLifecycleOwnerLiveData() 然后用与片段视图对应的新初始化的 LifecycleOwner 更新。 onViewCreated() 生命周期回调也在此时被调用

这是设置视图初始状态的合适位置,开始观察其回调更新片段视图的 LiveData 实例 ...

但是,当 Activity 从其

onCreate
回调控制导航时,片段视图的生命周期永远不会到达
STARTED
状态,也不会在显示片段 B 时下降到
DESTROYED
。因此,从片段 B 回到片段 A,前一个生命周期所有者观察 LiveData,片段的新生命周期所有者也试图观察它,抛出异常。

[编辑] 我一直试图找出可能触发此异常的更改。我使用

2.5.1
2.6.0
androidx.lifecycle:lifecycle-viewmodel-ktx
版本运行代码,我发现异常是由版本
2.6.0
(和
2.6.1
)触发的,但版本
2.5.1
没有触发。我还在片段回调中添加了日志,发现两个版本都调用了
onViewCreated

onCreateView: Fragment view is INITIALIZED
onViewCreated: Fragment view is INITIALIZED
onDestroyView: Fragment view is INITIALIZED

[/编辑]

我还记录了用户“手动”导航到另一个片段并且片段视图的生命周期从

INITIALIZED
CREATED
向下到
DESTROYED

问题

出现了几个问题:生命周期可以从

INITIALIZED
直接进入
DESTROYED
状态吗?或者它没有向下走是我这边的错误?

如果不是,正确的做法是什么?一旦生命周期达到

CREATED
状态,是否应该稍后观察LiveData?

或者活动不应该这么早导航到另一个片段?它是否应该在导航离开之前等待片段显示视图(显然这对用户体验来说并不理想)?

android kotlin android-fragments android-livedata android-lifecycle
1个回答
0
投票

我不认为这是一个明确的答案,但我看到了两种解决问题的方法。

一个是降级jetpack生命周期库,特别是

androidx.lifecycle:lifecycle-viewmodel-ktx
,到
2.5.1

另一个是从activity的

onStart
回调导航到其他Fragments。

© www.soinside.com 2019 - 2024. All rights reserved.