Quali metodi di gestione degli errori nelle coroutine conosci?
sobes.tech AI
Risposta dell'AI
-
Uso di blocchi
try...catch. Metodo standard per la gestione delle eccezioni. Funziona all'interno di una coroutine.// Applicazione di try-catch suspend fun fetchData(): String { return try { // Operazione che può generare un'eccezione throw Exception("Errore nel caricamento dei dati") "Dati caricati con successo" } catch (e: Exception) { "Errore: ${e.message}" } }try...catchnon è adatto per gestire eccezioni non catturate lanciate da coroutine figlie, eseguite in un altroCoroutineScope. -
CoroutineExceptionHandler. Intercetta le eccezioni non gestite lanciate da coroutine avviate in questoCoroutineScopeo nei suoiCoroutineScopefigli.// CoroutineExceptionHandler val handler = CoroutineExceptionHandler { _, exception -> println("Eccezione intercettata: $exception") } // Applicazione di CoroutineExceptionHandler GlobalScope.launch(handler) { // Coroutine che può generare un'eccezione throw Exception("Errore nella coroutine") }CoroutineExceptionHandlersi attiva solo per eccezioni non gestite dal meccanismo di concorrenza strutturata. -
SupervisorJobesupervisorScope. A differenza di unJobnormale, quando una coroutine figlia con errore causa l'annullamento delJobgenitore,SupervisorJobnon annulla ilJobgenitore in caso di errore della coroutine figlia.supervisorScopecrea unoCoroutineScopecon unSupervisorJob.// Uso di supervisorScope suspend fun loadMultipleData() = supervisorScope { val data1 = async { // Può generare un'eccezione throw Exception("Errore nei dati 1") "Dati 1" } val data2 = async { "Dati 2" } // Gestione dell'eccezione per un async specifico try { println("Risultato 1: ${data1.await()}") } catch (e: Exception) { println("Errore nel caricamento dei dati 1: ${e.message}") } println("Risultato 2: ${data2.await()}") }Usato per compiti figli indipendenti, dove l'errore di uno non deve influenzare gli altri. Non sostituisce
try...catchoCoroutineExceptionHandler, ma modifica il comportamento di propagazione delle eccezioni. -
Propagazione delle eccezioni nella concorrenza strutturata. Per impostazione predefinita, un'eccezione in una coroutine figlia cancella la coroutine genitore e tutti i suoi fratelli.
// Esempio di propagazione dell'eccezione runBlocking { val job = launch { launch { // Coroutine figlia 1 delay(100) throw Exception("Errore in figlia 1") } launch { // Coroutine figlia 2 delay(200) println("Figlia 2 completata") } } try { job.join() } catch (e: Exception) { println("Eccezione catturata nel genitore: $e") } }Questo è il comportamento di default della concorrenza strutturata, che aiuta a evitare perdite di risorse e stati.
-
Uso di
asyncconawait(). Le eccezioni lanciate inasyncnon si propagano automaticamente. Sono memorizzate inDeferrede vengono lanciate solo al momento di chiamareawait().// Gestione delle eccezioni con async/await suspend fun safeAsyncCall() = coroutineScope { val deferred = async { throw Exception("Errore in async") "Risultato di async" } try { val result = deferred.await() println("Risultato: $result") } catch (e: Exception) { println("Eccezione catturata da async: ${e.message}") } }Questo permette di gestire gli errori in modo selettivo per ogni task asincrono.
| Metodo | Scopo | Gestisce uncaught? | Cambia propagazione? |
|---|---|---|---|
try...catch |
Gestione delle eccezioni nella coroutine corrente | No | No |
CoroutineExceptionHandler |
Cattura eccezioni non gestite nello Scope | Sì | No |
SupervisorJob/Scope |
Modifica il comportamento di propagazione delle eccezioni | No | Sì |
| Concorrenza strutturata | Annullamento automatico in caso di errore | Sì | Sì |
async + await() |
Propagazione ritardata delle eccezioni | No | Sì (prima di await) |