У меня проблема с выяснением того, как использовать каналы. Я ожидаю, что они передадут значение потребителю сразу после вызова send, вместо этого я получаю значения после загрузки данных из обоих источников.
MainActivity.kt
fun loadData() {
textView.text = "LOADING"
launch {
repository.loadData().consumeEach { loaded ->
withContext(Dispatchers.Main) {
logd("Presenting: ${loaded.size}, $loaded")
textView.text = loaded.joinToString { "$it\n" }
}
}
}
Repository.kt
suspend fun loadData(): ReceiveChannel<List<String>> {
return coroutineScope {
produce(capacity = 2) {
launch {
val localData = local.loadData()
send(localData)
}
launch {
val remoteData = remote.loadData()
send(remoteData)
}
}
}
}
Remote.kt
override val data: MutableList<String> = mutableListOf("R1", "R2", "R3", "R4", "R5")
override suspend fun loadData(): List<String> {
logd("Loading remote started")
val wait = Random.nextLong(0, 500)
delay(wait)
logd("Remote loading took $wait")
logd("Loading remote finished: ${data.size}, $data")
return data
}
Local.kt
override val data: MutableList<String> = mutableListOf("L1", "L2", "L3", "L4", "L5")
override suspend fun loadData(): List<String> {
logd("Loading local started")
val wait = Random.nextLong(1000, 2000)
delay(wait)
logd("Local loading took $wait")
logd("Loading local finished: ${data.size}, $data")
return data
}
Я получаю это внутри консоли
D/Local: Loading local started
D/Remote: Loading remote started
D/Remote: Remote loading took 265
D/Remote: Loading remote finished: 5, [R1, R2, R3, R4, R5]
D/Local: Local loading took 1650
D/Local: Loading local finished: 5, [L1, L2, L3, L4, L5]
D/DispatchedCoroutine: Presenting: 5, [R1, R2, R3, R4, R5]
D/DispatchedCoroutine: Presenting: 5, [L1, L2, L3, L4, L5]
Похоже, что данные из обоих источников испускаются после достижения емкости,Я ожидаю, что потребитель сможет получать данные сразу после их отправки.Таким образом, вывод консоли выглядит примерно так:
D/Local: Loading local started
D/Remote: Loading remote started
D/Remote: Remote loading took 265
D/DispatchedCoroutine: Presenting: 5, [R1, R2, R3, R4, R5]
D/Remote: Loading remote finished: 5, [R1, R2, R3, R4, R5]
D/Local: Local loading took 1650
D/Local: Loading local finished: 5, [L1, L2, L3, L4, L5]
D/DispatchedCoroutine: Presenting: 5, [L1, L2, L3, L4, L5]
Как мне этого добиться (используя значения сразу после их отправки) с помощью coroutine.Channel?
EDIT # 1:
После удаления coroutineScope{...}
из Repository#loadData()
он начал работать как положено.Но теперь у меня есть проблема, что я должен передать область видимости в качестве параметра функции, который выглядит мне безобразно.
Repository.kt
suspend fun loadData(scope: CoroutineScope): ReceiveChannel<List<String>> {
return scope.produce(capacity = 2) {
launch {
val localData = local.loadData()
send(localData)
}
launch {
val remoteData = remote.loadData()
send(remoteData)
}
invokeOnClose {
logd("Closing channel")
}
}
}