微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用 repeatOnLifeCycle 从 UI 中的 Flow 收集

如何解决使用 repeatOnLifeCycle 从 UI 中的 Flow 收集

我开始用 LiveData 替换 Flow,因为它更灵活。但后来我发现您需要编写大量样板代码以从 UI 中的 Flow 进行观察。

StateFlow documentation中,它说

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 的方法。

详情请参考:https://proandroiddev.com/should-we-choose-kotlins-stateflow-or-sharedflow-to-substitute-for-android-s-livedata-2d69f2bd6fa5

第二个问题: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 举报,一经查实,本站将立刻删除。