#kotlin #kotlin-coroutines
Вопрос:
Я запускаю код A и получаю результат A. На мой взгляд, это должен быть результат Б.
Похоже, что flow.collect { value -> println(value) }
блок нужно выполнить.
Будет ли сбор блока потока выполняться ?
Код А
fun simple(): Flow<Int> = flow {
println("Flow started")
for (i in 1..3) {
delay(300)
emit(i)
}
}
fun main() = runBlocking<Unit> {
println("Calling simple function...")
val flow = simple()
println("Calling collect...")
flow.collect { value -> println(value) } //Block?
println("Calling collect again...")
}
Результат А
Calling simple function...
Calling collect...
Flow started
1
2
3
Calling collect again...
Результат B
Calling simple function...
Calling collect...
Flow started
Calling collect again...
1
2
3
Кстати, я запускаю код 1 и получаю результат 1, как и ожидал.
Код 1
fun simple(): Flow<Int> = flow {
for (i in 1..3) {
delay(100)
emit(i)
}
}
fun main() = runBlocking<Unit> {
launch {
for (k in 1..3) {
println("I'm not blocked $k")
delay(100)
}
}
simple().collect { value -> println(value) }
}
Результат 1
I'm not blocked 1
1
I'm not blocked 2
2
I'm not blocked 3
3
Ответ №1:
Функции приостановки не блокируются, но они синхронны, что означает, что выполнение кода в сопрограмме ожидает возвращения функции приостановки, прежде чем продолжить. Разница между вызовами функции приостановки и вызовами функции блокировки заключается в том, что поток освобождается для использования в других задачах, пока сопрограмма ожидает возврата функции приостановки.
collect
является функцией приостановки, которая внутренне повторно и синхронно вызывает свой лямбда-код (приостановка, а не блокировка) и не возвращается, пока поток не будет завершен.
launch
является асинхронной функцией, запускающей сопрограмму. Он возвращается немедленно, не дожидаясь завершения сопрограммы, поэтому код 1 вел себя так, как вы ожидали.