catch und onCompletion: Fehlerbehandlung in Flow
Fangen Sie Exceptions aus vorgelagerten Flow-Abschnitten ab und reagieren Sie auf Abschlussereignisse.
catch und onCompletion: Fehlerbehandlung in Flow ist eine kostenlose Kotlin Academy-Lektion auf CoddyKit. Dies ist Lektion 2 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des Kotlin Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der Kotlin Academy-Kurs umfasst insgesamt 4 Lektionen.
Grundlagen zu Flow-Ausnahmen
Ausnahmen in einem Flow beenden ihn. Ohne Behandlung wird die Ausnahme an den Collector weitergegeben und der Flow endet.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
try {
flow {
emit(1)
throw RuntimeException("stream error")
emit(2)
}.collect { println(it) }
} catch (e: Exception) {
println("Caught: ${e.message}")
}
}catch-Operator
catch behandelt Ausnahmen aus dem Upstream und kann Ersatzwerte ausgeben oder die Ausnahme erneut auslösen. Ausnahmen, die vom Collector selbst ausgelöst werden, fängt er nicht ab.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
flow {
emit(1)
throw RuntimeException("oops")
}.catch { e ->
println("Caught: ${e.message}")
emit(-1) // fallback value
}.collect { println(it) } // 1, then -1
}catch behandelt nur den Upstream
catch fängt nur Ausnahmen aus dem Flow-Builder und den Upstream-Operatoren ab – nicht aus dem collect-Lambda.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
try {
flowOf(1, 2, 3)
.catch { e -> println("upstream: ${e.message}") }
.collect {
if (it == 2) throw RuntimeException("collector error") // not caught by catch
println(it)
}
} catch (e: Exception) {
println("Collector exception: ${e.message}")
}
}Erneutes Auslösen in catch
Sie können die Ausnahme untersuchen und gezielt diejenigen erneut auslösen, die Sie nicht behandeln können.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
try {
flow {
emit(1)
throw IllegalStateException("state error")
}.catch { e ->
if (e is RuntimeException) { emit(-1); return@catch }
throw e // rethrow unknown exceptions
}.collect { println(it) }
} catch (e: Exception) {
println("Rethrown: ${e.message}")
}
}onCompletion-Operator
onCompletion wird ausgeführt, wenn der Flow beendet wird – normal oder mit einer Ausnahme. Sein Parameter cause ist bei einem Fehler nicht null.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
flowOf(1, 2, 3)
.onCompletion { cause ->
if (cause == null) println("Completed normally")
else println("Failed: ${cause.message}")
}
.collect { println(it) }
}onCompletion bei einem Fehler
onCompletion wird auch bei einer Upstream-Ausnahme ausgeführt. Es erhält die Ausnahme als cause, unterdrückt sie aber nicht – die Ausnahme wird weiterhin weitergegeben.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
try {
flow {
emit(1)
throw RuntimeException("error")
}.onCompletion { cause ->
println("onCompletion cause=${cause?.message}")
}.collect { println(it) }
} catch (e: Exception) {
println("outer catch: ${e.message}")
}
}catch und onCompletion kombinieren
Verwenden Sie catch, um sich zu erholen und Ersatzwerte auszugeben, und anschließend onCompletion, um unabhängig vom Ergebnis zu protokollieren oder Ressourcen freizugeben.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
flow {
emit("ok")
throw RuntimeException("network error")
}.catch { e ->
emit("fallback") // recover
}.onCompletion {
println("Stream done — release resources")
}.collect { println(it) }
}retry-Operator
retry(n) { ... } abonniert den Upstream-Flow bei einer Ausnahme bis zu n-mal erneut.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
var attempt = 0
fun unstableFlow() = flow {
attempt++
if (attempt < 3) throw RuntimeException("attempt $attempt failed")
emit("success on attempt $attempt")
}
fun main() = runBlocking {
unstableFlow()
.retry(3) { e -> println("retrying: ${e.message}"); true }
.collect { println(it) }
}retryWhen für benutzerdefinierte Logik
retryWhen stellt die Ausnahme und die Anzahl der Versuche bereit, sodass Sie einen Backoff hinzufügen oder filtern können, welche Ausnahmen eine Wiederholung auslösen.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
var n = 0
flow {
if (n++ < 2) throw IOException("IO error")
emit("done")
}.retryWhen { cause, attempt ->
cause is IOException && attempt < 3
}.collect { println(it) }
}onStart-Operator
onStart wird vor der ersten Ausgabe ausgeführt – nützlich, um Ladezustände anzuzeigen oder Ressourcen zu initialisieren, bevor Daten eintreffen.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
flowOf("data")
.onStart { emit("Loading...") }
.onCompletion { emit("Done") }
.collect { println(it) }
}Fehlerbehandlung bei echten API-Aufrufen
Umschließen Sie Repository-Flows mit catch, um Ausnahmen auf Domänenfehler abzubilden, und mit onCompletion, um Ladeanzeigen auszublenden.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
sealed class State { object Loading : State(); data class Data(val v: String) : State(); data class Error(val msg: String) : State() }
fun apiFlow(): Flow<String> = flow { delay(50); emit("response") }
fun uiFlow(): Flow<State> = apiFlow()
.map { State.Data(it) as State }
.onStart { emit(State.Loading) }
.catch { e -> emit(State.Error(e.message ?: "unknown")) }
fun main() = runBlocking { uiFlow().collect { println(it) } }Kurzer Test
Was ist die wichtigste Einschränkung des catch-Operators?
Zusammenfassung
catch behandelt Ausnahmen aus vorgelagerten Flows und kann Ersatzwerte emittieren. onCompletion wird immer ausgeführt (bei normalem Abschluss oder Fehler) und eignet sich für Aufräumarbeiten oder Protokollierung. Kombinieren Sie beide für robuste Flow-Pipelines mit retry/retryWhen.
Häufig gestellte Fragen
Ist die Lektion „catch und onCompletion: Fehlerbehandlung in Flow“ kostenlos?
Ja — der vollständige Text von „catch und onCompletion: Fehlerbehandlung in Flow“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des Kotlin Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der Kotlin Academy-Kurs umfasst insgesamt 4 Lektionen.
Was lerne ich in „catch und onCompletion: Fehlerbehandlung in Flow“?
Fangen Sie Exceptions aus vorgelagerten Flow-Abschnitten ab und reagieren Sie auf Abschlussereignisse. Du übst Kotlin Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.
Brauche ich Erfahrung, um Kotlin Academy zu starten?
Keine Vorkenntnisse erforderlich. Kotlin Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 2 von 4.
Wie lange dauert die Lektion „catch und onCompletion: Fehlerbehandlung in Flow“?
Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.
Kann ich in dieser Kotlin Academy-Lektion Code schreiben und ausführen?
Ja. Jede Kotlin Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.
Alle Lektionen in diesem Kurs
- Flow-Operatoren: map, filter, transform und take
- catch und onCompletion: Fehlerbehandlung in Flow
- combine und zip: Mehrere Flows zusammenführen
- flowOn und buffer: Kontext und Backpressure