Как слить производителей в котлин сопрограммы? - PullRequest
2 голосов
/ 13 июня 2019

Используя Rx, можно объединить несколько источников подписки, как показано ниже

// psudo data repository

fun getAllData(): Flowable<DataType> {
    return getCachedData().mergeWith(getRemoteData())
}

fun getCachedData(): Flowable<DataType> {
    // local database call
}

fun getRemoteData(): Flowable<DataType> {
    // network call
}

в коде выше getAllData() вернет данные КАК МОЖНО СКОРЕЕ один из возвращенных слитых Flowables, а затем отправит другой, как только будет готов.

Вопрос в том, как я могу достичь того же результата, используя produce? 1010 * Kotlin coroutine?

1 Ответ

1 голос
/ 13 июня 2019

Вы можете создать комбинированный канал с produce, в котором вы запускаете две сопрограммы, которые используют оба входных канала и повторно отправляют его в объединенный канал.

Вот функция, которая объединяет несколько каналов приема одного типав один.

/**
 * Merges multiple [channels] into one channel.
 * All elements of all channels are send to the combined channel in the order they arrive on the input channels.
 */
fun <T> CoroutineScope.mergeChannels(vararg channels: ReceiveChannel<T>) : ReceiveChannel<T> {
    return produce {
        channels.forEach {
            launch { it.consumeEach { send(it) }}
        }
    }
}

Вы можете использовать его так:

fun main() = runBlocking<Unit> {
    val every100Ms = produce {
        repeat(10) {
            send("every 100: $it")
            delay(100)
        }
    }

    val every200Ms = produce {
        repeat(10) {
            send("every 200: $it")
            delay(200)
        }
    }

    val combined = mergeChannels(every100Ms, every200Ms)
    combined.consumeEach { println(it) }
}
...