Wie man Koroutinen in Kotlin-Projekten einrichtet und verwendet?
sobes.tech KI
Antwort von AI
Um Coroutinen-Setup erfordert die Hinzufügung der entsprechenden Abhängigkeit in die build.gradle-Datei.
// build.gradle (Modul app)
dependencies {
//... andere Abhängigkeiten
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3") // Für JVM, Android, JS, Native
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3") // Für Android (wenn Dispatcher.Main benötigt wird)
}
Die Verwendung von Coroutinen umfasst:
-
Scope: Definition des Bereichs, in dem die Coroutinen ausgeführt werden und Verwaltung ihres Lebenszyklus.
GlobalScope: Anwendungsbereich, vorsichtig verwenden, da Speicherlecks möglich sind.CoroutineScope: Wird explizit erstellt, ermöglicht die Kontrolle der Abbruchfunktion.- Vorgegebene Bereiche in Frameworks (z.B.
lifecycleScopein Android ViewModel).
// Beispiel mit CoroutineScope val myScope = CoroutineScope(Dispatchers.Default + SupervisorJob()) // Erstellen eines Scopes mit Dispatcher und Job fun performBackgroundTask() { myScope.launch { // Starten einer Coroutine // Langer Rechenprozess } } fun cancelAllTasks() { myScope.cancel() // Alle Coroutinen im Scope abbrechen } -
Builder: Funktionen zum Starten von Coroutinen.
launch: Startet eine Coroutine, die kein Ergebnis explizit zurückgibt (Job).async: Startet eine Coroutine, die ein Ergebnis vom TypDeferredzurückgibt.
import kotlinx.coroutines.* suspend fun fetchData() = coroutineScope { // coroutineScope - Builder für strukturierte Konkurrenz val data1 = async { networkCall1() } // async gibt einen Deferred zurück val data2 = async { networkCall2() } // ... Verarbeitung der Daten nach Erhalt data1.await() // Ergebnis von Deferred holen, suspendiert die Coroutine bis zum Abschluss data2.await() } suspend fun networkCall1(): String { delay(1000) // Simulation einer Netzwerkanfrage return "Data 1" } suspend fun networkCall2(): String { delay(1500) return "Data 2" } fun startFetching() = runBlocking { // runBlocking - Builder zum Blockieren des aktuellen Threads (für main oder Tests) launch { // launch gibt einen Job zurück println("Daten werden abgerufen...") fetchData() println("Daten abgerufen!") } } -
Dispatcher: Bestimmen, auf welchem Thread oder Thread-Pool die Coroutine ausgeführt wird.
Dispatchers.Default: Für CPU-intensive Aufgaben.Dispatchers.IO: Für blockierende I/O-Operationen (Dateizugriff, Netzwerk).Dispatchers.Main: Haupt-Thread (nur für Android und Swing/JavaFX).Dispatchers.Unconfined: Führt die Coroutine im aufrufenden Thread aus, sie wird suspendiert und dann im Thread wieder aufgenommen, der sie wieder aufnimmt.
import kotlinx.coroutines.* fun simpleTask() { GlobalScope.launch(Dispatchers.IO) { // Dispatcher angeben // Ausführen einer I/O-Operation println("Ausführung im Thread: ${Thread.currentThread().name}") } } fun main() = runBlocking { launch(Dispatchers.Default) { println("Default-Thread: ${Thread.currentThread().name}") } launch(Dispatchers.Unconfined) { println("Unconfined-Thread 1: ${Thread.currentThread().name}") delay(100) // Suspendieren println("Unconfined-Thread 2: ${Thread.currentThread().name}") // Fortsetzen in anderem Thread (möglich) } delay(200) // Warten auf Abschluss der Coroutinen } -
Suspendierende Funktionen: Funktionen, die mit
suspendgekennzeichnet sind und suspendiert und wieder aufgenommen werden können, ohne den Thread zu blockieren. Können nur aus anderen suspendierenden Funktionen oder Coroutine-Blöcken aufgerufen werden. -
Abbruch und Fehlerbehandlung: Coroutinen unterstützen strukturierte Abbrüche und Fehlerweiterleitung.
- Abbruch:
import kotlinx.coroutines.* fun cancellableTask() = GlobalScope.launch { try { repeat(1000) { i -> println("Arbeiten $i ...") delay(100) // Suspendierende Funktion, die Abbruch respektiert } } catch (e: CancellationException) { println("Aufgabe wurde abgebrochen!") } finally { println("Aufräumen...") } } fun main() = runBlocking { val job = cancellableTask() delay(500) // Etwas warten job.cancelAndJoin() // Abbrechen und auf Abschluss warten } - Fehler: Bei
launchführt eine unbehandelte Ausnahme zum Absturz der Anwendung (bei Android standardmäßig). Beiasyncwird die Ausnahme beim Aufruf vonawait()ausgelöst. Für granularere Kontrolle werdenCoroutineExceptionHandleroderSupervisorJobverwendet.
import kotlinx.coroutines.* fun main() = runBlocking { val handler = CoroutineExceptionHandler { _, exception -> println("Fangene Ausnahme: $exception") } val job = GlobalScope.launch(handler) { // Handler anwenden throw IllegalStateException("Etwas ist schief gelaufen") } job.join() // Warten auf Abschluss } - Abbruch: