简体   繁体   English

如何从不同的 function 发出流量值? Kotlin 协程

[英]How to emit Flow value from different function? Kotlin Coroutines

I have a flow:我有一个流程:

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

and want to emit values with function:并想用 function 发出值:

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

But compiler does not allow me to do this, is there any workarounds to solve this problem?但是编译器不允许我这样做,有什么解决方法可以解决这个问题吗?

The answer of Animesh Sahu is pretty much correct. Animesh Sahu 的答案非常正确。 You can also return a Channel as a flow (see consumeAsFlow or asFlow on a BroadcastChannel ).您还可以将Channel作为流返回(请参阅BroadcastChannel上的consumeAsFlowasFlow )。

But there is also a thing called StateFlow currently in development by Kotlin team, which is, in part, meant to implement a similar behavior, although it is unknown when it is going to be ready.但是目前 Kotlin 团队正在开发一个叫做StateFlow的东西,这在某种程度上是为了实现类似的行为,尽管它什么时候准备好还不得而知。

EDIT: StateFlow and SharedFlow have been released as part of a stable API ( https://blog.jetbrains.com/kotlin/2020/10/kotlinx-coroutines-1-4-0-introducing-stateflow-and-sharedflow/ ).编辑: StateFlowSharedFlow已作为稳定 API 的一部分发布( https://blog.jetbrains.com/kotlin/2020/10/kotlinx-coroutines-1-4-0-introducing-stateflow-and-sharedflow/ ) . These tools can and should be used when state management is required in an async execution context.当异步执行上下文中需要 state 管理时,可以并且应该使用这些工具。

You can use StateFlow for such use case.您可以将StateFlow用于此类用例。 Here's a sample code.这是一个示例代码。

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
}

You can test this code by running below snippet.您可以通过运行以下代码段来测试此代码。

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

Flow is self contained, once the block (lambda) inside the flow is executed the flow is over, you've to do operations inside and emit them from there.流程是自包含的,一旦流程中的块(lambda)被执行,流程就结束了,您必须在内部进行操作并从那里发出它们。

Here is the similar github issue , says:这是类似的github 问题,说:

Afaik Flow is designed to be a self contained, replayable, cold stream, so emission from outside of it's own scope wouldn't be part of the contract. Afaik Flow 被设计成一个独立的、可重放的、冷的 stream,因此从它自己的 scope 外部排放不会成为合同的一部分。 I think what you're looking for is a Channel.我认为你正在寻找的是一个频道。

And IMHO you're probably looking at the Channels , or specifically a ConflatedBroadcastChannel for multiple receivers.恕我直言,您可能正在查看Channels ,或者特别是针对多个接收器的ConflatedBroadcastChannel The difference between a normal channel and a broadcast channel is that multiple receivers can listen to a broadcast channel using openSubscription function which returns a ReceiveChannel associated with the BroadcastChannel.普通频道和广播频道之间的区别在于,多个接收者可以使用openSubscription function 收听广播频道,它返回与广播频道关联的 ReceiveChannel。

Use a SharedStateFlow it has got everything you need.使用SharedStateFlow它拥有你需要的一切。

Initialization of your flow:流程的初始化:

val myFlow = MutableSharedFlow<Message>()

and now it should just work as you were trying earlier with:现在它应该像你之前尝试的那样工作:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM