我试着用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)打印0,而它应该打印99.我已经跟踪了this documentation about stateIn个,但仍然找不到问题所在.有人知道我哪里做错了吗?

推荐答案

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

使用不带参数的MuableSharedFlow()构造函数创建的共享流的默认实现没有重放缓存或额外的缓冲区.对这种共享流的发出调用暂停,直到所有订阅者都收到发出的值和returns immediately if there are no subscribers.

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

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

这意味着状态流的协程仅在第一个订阅者开始收集状态流时才开始收集源.state flow上没有订户的原因是,在你到达emits 台之前,你的emits 还没有来得及拨打collect.

当您调用launch时,您正在启动一个异步操作.launch中的代码与其后面的代码同时运行.由于您是在runBlocking的作用域内运行这launch,这意味着它与main的其余代码在同一线程上运行,这意味着launch的主体在主函数主体实际挂起之前不能开始运行.在这里,它只有在达到emit()时才会暂停.

Kotlin相关问答推荐

如何在Kotlin中模拟www.example.com()?

用浮点数或十进制数给出错误答案的阶乘计算

如何接受任何派生类KClass

T和T有什么区别:任何>

使用启动或使用 coroutineScope 启动协程之间的区别

在 Kotlin 中,如何绑定扩展方法以在接收器范围函数中工作

为什么 Kotlin 需要函数引用语法?

如何创建 Kotlin DSL - DSL 语法 Kotlin

比较 Kotlin 中的可比对象列表

Kotlin 解构超过五个组件

runOnUiThread 没有调用

为什么 Dialog 没有 NavController [Missing]?

Kotlin如何分派invoke操作符?

Kotlin 中的内联构造函数是什么?

用mockk验证属性设置程序吗?

使用主构造函数时使用Kotlin getter/setter

将 Double 转换为 ByteArray 或 Array Kotlin

查找是否在列表中找到具有特定属性值的元素

Kotlin 中内部可见性修饰符的范围

在多平台子元素中使用kapt