如何解决使用 repeatOnLifeCycle 从 UI 中的 Flow 收集
我开始用 LiveData
替换 Flow
,因为它更灵活。但后来我发现您需要编写大量样板代码以从 UI 中的 Flow
进行观察。
LiveData.observe()
在视图进入 STOPPED
状态时自动注销消费者,而从 StateFlow
或任何其他流收集不会自动停止收集。要实现相同的行为,您需要从 Lifecycle.repeatOnLifecycle
块中收集流。
Manuel Vivo 在 article 中也提到使用从 lifecycleScope.launchWhenX
收集是危险的,不应在 UI 中使用,因为生产者流不会停止发射。
他推荐我们使用
// Listen to multiple flows
lifecycleScope.launch {
lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
// As collect is a suspend function,if you want to collect
// multiple flows in parallel,you need to do so in
// different coroutines
launch {
flow1.collect { /* Do something */ }
}
launch {
flow2.collect { /* Do something */ }
}
}
}
样板代码太多。难道不能像 LiveData
那样在两条班轮中完成吗?
viewmodel.movieData.observe(viewLifecycleOwner) {
...
}
为什么在 UI 中从 Flow
收集如此复杂?是否建议使用 asLiveData()
将 Flow 转换为 LiveData?
解决方法
首先回答你的第一个问题:Flow
是冷流。 Flow 是无状态的。如果您提供Flow
,则表示您需要经常构建和收集Flow。
另外一种情况,如果提供了Hot Flow,比如(StatedFlow),虽然hot flow提供了状态(.value),但它对Android的生命周期一无所知。正如你所说,你可以使用launchWhenXXX()来收集流量。
使用launchWhenXXX()时,一定要注意热流的生命周期。什么时候开始collect
,什么时候结束collect
,这些都需要注意。所以看起来很麻烦。当然,Flow 是一种摆脱使用 LiveData 的方法。
第二个问题:LiveData 管理 Android 的生命周期。 Flow.asLiveData() 是完全可取的。这时候只需要简单的 Observe 即可。
,您可以构建扩展以减少样板
inline fun <T> Flow<T>.collectIn(
owner: LifecycleOwner,minActiveState: Lifecycle.State = Lifecycle.State.STARTED,coroutineContext: CoroutineContext = EmptyCoroutineContext,crossinline action: suspend CoroutineScope.(T) -> Unit
) = owner.addRepeatingJob(minActiveState,coroutineContext) {
collect {
action(it)
}
}
这使得收集流程类似于 LiveData
flow.collectIn(viewLifecycleOwner){ /* do stuff */ }
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。