Jakie metody obsługi błędów w korutynach znasz?
sobes.tech AI
Odpowiedź od AI
-
Użycie bloków
try...catch. Standardowa metoda obsługi wyjątków. Działa wewnątrz korutyny.// Zastosowanie try-catch suspend fun fetchData(): String { return try { // Operacja, która może wyrzucić wyjątek throw Exception("Błąd ładowania danych") "Dane pomyślnie załadowane" } catch (e: Exception) { "Błąd: ${e.message}" } }try...catchnie jest odpowiedni do obsługi nieprzechwyconych wyjątków wyrzucanych przez korutyny potomne, uruchomione w innymCoroutineScope. -
CoroutineExceptionHandler. Przechwytuje nieobsłużone wyjątki wyrzucane przez korutyny uruchomione w tymCoroutineScopelub jegoCoroutineScopepotomne.// CoroutineExceptionHandler val handler = CoroutineExceptionHandler { _, exception -> println("Przechwycono wyjątek: $exception") } // Zastosowanie CoroutineExceptionHandler GlobalScope.launch(handler) { // Korutyna, która może wyrzucić wyjątek throw Exception("Błąd w korutynie") }CoroutineExceptionHandlerdziała tylko dla nieobsłużonych wyjątków, które nie są obsłużone przez mechanizm zorganizowanej współbieżności. -
SupervisorJobisupervisorScope. W przeciwieństwie do zwykłegoJob, gdy korutyna potomna z błędem powoduje anulowanieJobnadrzędnego,SupervisorJobtego nie robi.supervisorScopetworzyCoroutineScopezSupervisorJob.// Użycie supervisorScope suspend fun loadMultipleData() = supervisorScope { val data1 = async { // Może wyrzucić wyjątek throw Exception("Błąd w danych 1") "Dane 1" } val data2 = async { "Dane 2" } // Obsługa wyjątku dla konkretnej async try { println("Wynik 1: ${data1.await()}") } catch (e: Exception) { println("Błąd podczas ładowania danych 1: ${e.message}") } println("Wynik 2: ${data2.await()}") }Używany dla niezależnych zadań potomnych, gdzie błąd jednego nie powinien wpływać na inne. Nie zastępuje
try...catchaniCoroutineExceptionHandler, raczej zmienia zachowanie propagacji wyjątków. -
Propagacja wyjątków w zorganizowanej współbieżności. Domyślnie, wyjątek w korutynie potomnej powoduje anulowanie korutyny nadrzędnej i wszystkich jej braci.
// Przykład propagacji wyjątku runBlocking { val job = launch { launch { // Korutyna potomna 1 delay(100) throw Exception("Błąd w potomnej 1") } launch { // Korutyna potomna 2 delay(200) println("Potomna 2 zakończyła się") } } try { job.join() } catch (e: Exception) { println("Przechwycono wyjątek w nadrzędnym: $e") } }To jest domyślne zachowanie zorganizowanej współbieżności, które pomaga unikać wycieków zasobów i stanów.
-
Użycie
asynczawait(). Wyjątki wyrzucane wasyncnie są automatycznie propagowane. Są przechowywane wDeferredi wyrzucane dopiero przy wywołaniuawait().// Obsługa wyjątków z async/await suspend fun safeAsyncCall() = coroutineScope { val deferred = async { throw Exception("Błąd w async") "Wynik async" } try { val result = deferred.await() println("Wynik: $result") } catch (e: Exception) { println("Przechwycono wyjątek z async: ${e.message}") } }Pozwala to na selektywną obsługę błędów dla każdego zadania asynchronicznego.
| Metoda | Cel | Obsługuje uncaught? | Zmienia propagację? |
|---|---|---|---|
try...catch |
Obsługa wyjątków w bieżącej korutynie | Nie | Nie |
CoroutineExceptionHandler |
Przechwytuje nieobsłużone wyjątki w Scope | Tak | Nie |
SupervisorJob/Scope |
Zmienia zachowanie propagacji wyjątków | Nie | Tak |
| Strukturalna współbieżność | Automatyczne anulowanie przy błędzie | Tak | Tak |
async + await() |
Opóźniona propagacja wyjątków | Nie | Tak (przed await) |