Как передать значение потока из другой функции? Kotlin сопрограммы - PullRequest
2 голосов
/ 07 мая 2020

У меня есть поток:

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

, и я хочу выдавать значения с помощью функции:

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

Но компилятор не позволяет мне это сделать, есть ли какие-либо обходные пути для решения эта проблема?

Ответы [ 3 ]

2 голосов
/ 07 мая 2020

Ответ аниме sh Саху в значительной степени правильный. Вы также можете вернуть Channel в виде потока (см. consumerAsFlow или asFlow в BroadcastChannel ).

Но есть также вещь под названием StateFlow, которая в настоящее время разрабатывается командой Kotlin, которая отчасти предназначена для реализации аналогичного поведения, хотя неизвестно, когда она будет готова.

1 голос
/ 23 мая 2020

Вы можете использовать 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>
1 голос
/ 07 мая 2020

Поток самодостаточен, как только блок (лямбда) внутри потока выполнен, поток завершается, вы должны выполнять операции внутри и испускать их оттуда.

Вот аналогичный github issue , говорит:

Afaik Flow спроектирован как самодостаточный, воспроизводимый, холодный поток, поэтому выбросы за пределами его собственной области не будут частью контракта. Я думаю, что вы ищете канал.

И ИМХО вы, вероятно, смотрите на каналы или, в частности, на ConflatedBroadcastChannel для нескольких приемники. Разница между обычным каналом и широковещательным каналом заключается в том, что несколько получателей могут прослушивать широковещательный канал с помощью функции openSubscription , которая возвращает ReceiveChannel, связанный с BroadcastChannel.

...