11

我有一个流程:

val myflow = kotlinx.coroutines.flow.flow<Message>{}

并想用函数发出值:

override suspend fun sendMessage(chat: Chat, message: Message) {
    myflow.emit(message)
}

但是编译器不允许我这样做,有什么解决方法可以解决这个问题吗?

4

4 回答 4

8

您可以将StateFlow用于此类用例。这是一个示例代码。

import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*

val chatFlow = MutableStateFlow<String>("")

fun main() = runBlocking {

    // Observe values
    val job = launch {
        chatFlow.collect {
            print("$it ")
        }
    }

    // Change values
    arrayOf("Hey", "Hi", "Hello").forEach {
        delay(100)
        sendMessage(it)
    }

    delay(1000)

    // Cancel running job
    job.cancel()
    job.join()
}

suspend fun sendMessage(message: String) {
    chatFlow.value = message
}

您可以通过运行以下代码段来测试此代码。

<iframe src="https://pl.kotl.in/DUBDfUnX3" style="width:600px;"></iframe>

于 2020-05-23T05:13:48.530 回答
7

Animesh Sahu 的答案非常正确。您还可以将Channel作为流返回(请参阅BroadcastChannel上的consumeAsFlowasFlow)。

但是 Kotlin 团队目前正在开发一个东西StateFlow,这部分是为了实现类似的行为,尽管它什么时候准备好还不得而知。

编辑:StateFlowSharedFlow已作为稳定 API 的一部分发布(https://blog.jetbrains.com/kotlin/2020/10/kotlinx-coroutines-1-4-0-introducing-stateflow-and-sharedflow/)。当异步执行上下文中需要状态管理时,可以并且应该使用这些工具。

于 2020-05-07T11:46:13.683 回答
1

使用SharedStateFlow它有你需要的一切。

流程的初始化:

val myFlow = MutableSharedFlow<Message>()

现在它应该可以像您之前尝试的那样工作:

override suspend fun sendMessage(chat: Chat, message: Message) {
    myFlow.emit(message)
}
于 2021-10-05T09:22:28.377 回答
1

流程是自包含的,一旦流程中的块(lambda)被执行,流程就结束了,您必须在内部进行操作并从那里发出它们。

这是类似的github问题,说:

Afaik Flow 被设计成一个独立的、可重放的、冷流,因此来自其自身范围之外的发射不会成为合同的一部分。我认为你正在寻找的是一个频道。

恕我直言,您可能正在查看Channels,或者特别是针对多个接收器的ConflatedBroadcastChannel 。普通频道和广播频道的区别在于,多个接收者可以使用openSubscription函数收听广播频道,该函数返回与 BroadcastChannel 关联的 ReceiveChannel。

于 2020-05-07T10:34:24.180 回答