Sobes.tech
Middle

Was wissen Sie über Fehlerbehandlung in Flow?

sobes.tech KI

Antwort von AI

Flow in Kotlin Coroutines bietet mehrere Möglichkeiten zur Fehlerbehandlung:

  1. Operator catch: Abfängt Ausnahmen im aufsteigenden Strom und ermöglicht es, eine Aktion auszuführen (z.B. Protokollierung, Rückgabe von Ersatzdaten) oder den Strom zu ersetzen.

    flow {
        emit(1)
        throw RuntimeException("Ein Fehler ist aufgetreten")
    }.catch { e: Throwable ->
        // Fehlerbehandlung
        emit(-1) // Anderen Wert bei Fehler ausgeben
    }.collect { value ->
        // Verarbeitung der Werte
    }
    
  2. try-catch Block: Klassischer Weg, Ausnahmen um einen Codeabschnitt herum zu behandeln, inklusive der Sammlung von Flow.

    try {
        flow {
            emit(1)
            throw RuntimeException("Ein Fehler ist aufgetreten")
        }.collect { value ->
            // Verarbeitung der Werte
        }
    } catch (e: Throwable) {
        // Fehlerbehandlung
    }
    

    Dieser Ansatz fängt Fehler ab, die während der Sammlung von Flow auftreten, aber nicht Fehler, die vom Flow-Emitter vor der Sammlung verursacht werden.

  3. Operator onEach mit try-catch: Wenn Fehler für jedes Element einzeln behandelt werden sollen.

    flow {
        emit(1)
        emit(2)
        throw RuntimeException("Fehler nach 2")
        emit(3)
    }.onEach { value ->
        try {
            // Verarbeitung jedes Elements
            if (value == 2) throw IllegalArgumentException("Ungültiger Wert 2")
        } catch (e: Throwable) {
            // Fehlerbehandlung für einen bestimmten Wert
            println("Fehler für Wert $value: ${e.message}")
            // Fehler weiterwerfen, um den Strom zu stoppen
            throw e
        }
    }.catch { e: Throwable ->
        // Fehlerbehandlung, die in onEach nicht abgefangen wurde, oder Fehler, die nach onEach geworfen wurden
        println("Endgültiger Fehler: ${e.message}")
    }.collect { value ->
        println("Gesammelter Wert: $value")
    }
    
  4. Operator retry / retryWhen: Ermöglichen es, die Quelle des Flows bei Fehlern zu wiederholen.

    • retry: Wiederholt einfach den Versuch eine festgelegte Anzahl von Malen.
    • retryWhen: Ermöglicht es, eine Bedingung für das Wiederholen festzulegen.
    var attempt = 0
    flow {
        println("Versuch ${++attempt}")
        if (attempt < 3) throw RuntimeException("Wiederholung")
        emit(10)
    }.retryWhen { cause, attempt ->
        // Logik zur Bestimmung, ob wiederholt werden soll
        cause is RuntimeException && attempt < 3
    }.collect { value ->
        println("Erfolg: $value")
    }
    
  5. Fehlerweiterleitung: Nicht explizit abgefangene Fehler werden nach oben in der Flow-Kette propagiert und können in einem try-catch-Block um den Flow-Sammler oder mit dem catch-Operator abgefangen werden.

Wichtig ist zu verstehen, dass der catch-Operator Fehler im aufsteigenden Strom (upstream) abfängt. Fehler, die im absteigenden Strom (downstream) nach catch auftreten, werden nicht abgefangen. Für die Behandlung solcher Fehler muss ein weiterer catch weiter unten in der Kette oder ein try-catch um den Sammler verwendet werden.

Allgemeine Empfehlung: Fehlerbehandlung so nah wie möglich an der Fehlerquelle platzieren, wenn möglich, aber beachten, dass catch nur den aufsteigenden Strom behandelt.