Flow.stateIn() 没有从它的源代码接收新值



我尝试使用stateIn将几个SharedFlow组合成一个StateFlow。但我的StateFlow似乎没有更新后,我发出新的价值,它的SharedFlow源。我发现问题出在我如何使用stateIn

这是我使用的简化代码(你可以从kotlin playground运行它)。

import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
fun main() = runBlocking {
val sourceFlow = MutableSharedFlow<Int>()
val stateFlow = sourceFlow.stateIn(GlobalScope, SharingStarted.Lazily, 0)
val job = launch { stateFlow.collect() }
sourceFlow.emit(99)
println(stateFlow.value)
job.cancel()
}

println(stateFlow.value)在应该打印99时打印出0。我已经完成了关于stateIn的文档,但仍然找不到问题。有人知道我哪里做错了吗?

简短的回答是,当发出99时没有开始收集,因此该值被简单地丢弃。这是SharedFlow文档中描述的无缓冲共享流的预期行为:

使用MutableSharedFlow()构造函数创建的共享流的默认实现,没有参数,没有重播缓存,也没有额外的缓冲区。对这种共享流的emit调用将挂起,直到所有订阅者接收到发出的值,如果没有订阅者,则立即返回。.

sourceFlow(共享流)上没有订阅者的原因是您在此流上使用SharingStarted.Lazily调用stateIn():

共享在第一个订阅者出现时开始并且永不停止

这意味着只有当第一个订阅者开始收集状态流时,状态流的协程才开始收集源。在状态流上没有订阅者的原因是,在到达emit之前,您的launch还没有时间调用collect

当你调用launch时,你正在启动一个异步操作。launch内部的代码与后面的代码并发运行。由于您在runBlocking的作用域中运行这个launch,这意味着它与main的其他代码在同一个线程上运行,这意味着launch的主体在主函数的主体实际挂起之前无法开始运行。在这里,它只在到达emit()时暂停。

最新更新