Reaktive Programmierung in Kotlin: Die Bibliothek kotlinx.coroutines und Flow

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Reaktive Programmierung in Kotlin: Die Kraft von kotlinx.coroutines und Flow

\n\n

Reaktive Programmierung ist ein Paradigma, das auf die asynchrone Verarbeitung von Datenströmen und die Verbreitung von Änderungen ausgerichtet ist. Im Kotlin-Ökosystem ist die Bibliothek kotlinx.coroutines das wichtigste Werkzeug zur Implementierung reaktiver Muster, genauer gesagt ihre Komponente Flow. Im Gegensatz zu RxJava ist Flow eng in Coroutinen integriert, was den Code prägnanter und sicherer macht.

\n\n

Grundlegende Konzepte von Flow

\n\n

Flow ist ein kalter asynchroner Datenstrom, der Werte sequenziell emittiert. Er unterstützt:

\n
    \n
  • Kalte Ströme — Daten werden nur dann generiert, wenn ein Abonnent (terminaler Operator) vorhanden ist.
  • \n
  • Ausführungskontext — Der Strom kann zwischen verschiedenen Coroutinen-Dispatchern wechseln.
  • \n
  • Abbruch durch Coroutinen — Der Abbruch der übergeordneten Coroutine beendet Flow automatisch.
  • \n
\n\n

Installation und Einrichtung

\n

Um Flow zu verwenden, fügen Sie die Abhängigkeit in build.gradle.kts hinzu:

\n
dependencies {\n    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.1")\n}
\n\n

Erstellen und Konsumieren von Flow

\n

Erstellen wir einen einfachen Zahlenstrom mit Verzögerung:

\n
import kotlinx.coroutines.*\nimport kotlinx.coroutines.flow.*\n\nfun simpleFlow(): Flow<Int> = flow {\n    for (i in 1..5) {\n        delay(100) // Simulation asynchroner Arbeit\n        emit(i)    // Wert emittieren\n    }\n}\n\nfun main() = runBlocking {\n    simpleFlow().collect { value ->\n        println("Erhalten: $value")\n    }\n}
\n

In diesem Beispiel erstellt flow { ... } einen kalten Strom, und collect ist der terminale Operator, der die Ausführung startet.

\n\n

Datentransformation mit Operatoren

\n

Flow bietet eine umfangreiche Sammlung von Operatoren, ähnlich wie RxJava:

\n
    \n
  • map — transformiert jeden Wert.
  • \n
  • filter — filtert Werte nach einer Bedingung.
  • \n
  • flatMapConcat — verbindet Ströme sequenziell.
  • \n
  • catch — behandelt Ausnahmen innerhalb des Stroms.
  • \n
\n

Beispiel mit Operatoren:

\n
fun transformFlow(): Flow<String> = flow {\n    emit("Kotlin")\n    emit("Java")\n    emit("Python")\n}.map { it.lowercase() }\n .filter { it.startsWith("k") }\n\nfun main() = runBlocking {\n    transformFlow().collect { println(it) }\n    // Ausgabe: kotlin\n}
\n\n

Fehlerbehandlung und Abschluss

\n

Flow ermöglicht die elegante Behandlung von Ausnahmen mit catch und die Ausführung von Abschlussaktionen über onCompletion:

\n
fun errorProneFlow(): Flow<Int> = flow {\n    emit(1)\n    emit(2)\n    throw RuntimeException("Fehler!")\n    emit(3) // wird nicht ausgeführt\n}\n\nfun main() = runBlocking {\n    errorProneFlow()\n        .catch { e -> println("Fehler abgefangen: ${e.message}") }\n        .onCompletion { println("Strom abgeschlossen") }\n        .collect { println(it) }\n}\n// Ausgabe: 1, 2, Fehler abgefangen: Fehler!, Strom abgeschlossen
\n\n

Heiße Ströme: StateFlow und SharedFlow

\n

Im Gegensatz zum kalten Flow sind StateFlow und SharedFlow heiße Ströme, die einen Zustand speichern und mehrere Abonnenten haben können.

\n\n

StateFlow

\n

Wird zum Speichern und Beobachten des Zustands verwendet (z. B. in ViewModel):

\n
class CounterViewModel {\n    private val _counter = MutableStateFlow(0)\n    val counter: StateFlow<Int> = _counter.asStateFlow()\n\n    fun increment() {\n        _counter.value++\n    }\n}\n\n// In Activity oder Fragment\nlifecycleScope.launch {\n    viewModel.counter.collect { value ->\n        textView.text = "Zähler: $value"\n    }\n}
\n\n

SharedFlow

\n

Geeignet für

Empfehlungen