如何解决在两个片段之间共享 ViewModel 中的 MutableStateFlow 冷流
我遇到了在两个片段之间共享的 MutableStateFlow 属性的问题。
使其易于理解:
我有一个 Basicviewmodel
,由于导航图的实现,它应该始终是两个片段的一个实例
private val basicviewmodel: basicviewmodel by navGraphviewmodels(R.id.basic_graph) { defaultviewModelProviderFactory }
这个 viewmodel 有一个 MutableStateFlow
属性声明如下
private val _basicProperty = MutableStateFlow<Basicclass?>(null)
val basicProperty : Flow<Basicclass?> = _basicId
.filterNotNull()
.flatMapConcat { someRepository.getBasicProperty(it) }
.onEach { _basicProperty.value = it }
.catch { }
然后,我使用导航图在导航中声明了 FragmentA
和 FragmentB
,这些导航图类似地调用了该属性,就像这样
basicviewmodel.basicProperty
.filterNotNull()
.mapNotNull { it.innerProperty}
.onEach { doSomething(it) }
.launchIn(viewLifecycleOwner.lifecycleScope)
一切看起来都很好,但是当我导航到 FragmentA
时,BasicProperty 加载流程(从 WebApi 加载数据)然后导航到 FragmentB
并且流程再次加载而不是调用已经加载的数据在应用中看起来有点滞后,因为重新加载
问题:我应该做什么/更改以从 Basicviewmodel
中的 FragmentB
获取现有数据?
解决方法
您的 _basicProperty
是一个热门的 StateFlow,但您从不使用它来收集任何东西。您公开的属性 basicProperty
是一个冷流,因此每个收集它的订阅者都将开始新的冷流运行。这些冷流中的每一个都会将其更新发布到 MutableStateFlow,因此在这一点上,其状态是不可预测的,因为它显示了共享冷流的任何收集器正在执行的最新操作。
我认为您想要的是共享一个执行流程。因此,您应该有一个执行连接的 StateFlow,如下所示:
val basicProperty : StateFlow<BasicClass?> = _basicId
.filterNotNull()
.flatMapConcat { someRepository.getBasicProperty(it) }
.catch { }
.stateIn(viewModelScope,SharingStarted.Eagerly,null)
在每个 Fragment 来收集它之前,您的原始代码不会启动流程。但此代码对 stateIn
的调用在 viewModelScope
中启动了一次流(在本例中,由于 Eagerly
参数而立即)。
现在这个流程只运行一次。您仍然可以像之前那样让每个 Fragment 运行自己的下游流。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。