Ошибка внутри потока в Kotlin
Исключение в строителе или в операторе рвет
корутину сбора, если его не обработать.
Функцию catch вешают на Flow: при
ошибке вызывается переданная лямбда, и поток
может завершиться штатно или отдать запасное
значение.
Падение внутри emit ловят до того, как
collect увидит необработанное
исключение:
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.runBlocking
fun main() {
runBlocking {
val risky = flow {
emit(1)
error("broken")
}.catch { cause ->
println("handled")
}
risky.collect { n ->
println(n)
}
}
}
Сначала печатается 1, затем метка
"handled". Функция catch срабатывает
на ошибке после первого элемента и не дает
сбору упасть наружу.
Из обработчика можно отправить замещающие данные через тот же приемник:
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.runBlocking
fun main() {
runBlocking {
val risky = flow<String> {
emit("ok")
error("fail")
}.catch { emit("fallback") }
risky.collect { line ->
println(line)
}
}
}
В консоли "ok" и "fallback".
Вторая строка приходит уже из catch,
а не из исходного строителя.
Поток отдает 5, затем бросает
исключение с текстом "stop".
Подключите catch, который печатает
"recovered", и соберите поток в
runBlocking.
После строки "live" вызовите
error. В catch отправьте
"spare" и убедитесь, что сбор
заканчивается без необработанного падения.