O que acontece com uma coroutine quando ocorre uma exceção?
sobes.tech IA
Resposta da IA
Quando ocorre uma exceção dentro de uma coroutine, a dependência do tipo de exceção (e as configurações do dispatcher/contexto) determina como ela será tratada.
-
Exceção não tratada: Se a exceção não for capturada dentro da coroutine, ela propaga-se para cima na hierarquia de coroutines até ao
JobouCoroutineScopemais próximo. O comportamento depende do tipo deJob:Job: Por padrão, quando ocorre uma exceção numa coroutine filha, oJobpai é cancelado, levando ao cancelamento de todas as suas outras coroutines filhas. A exceção é propagada para cima.SupervisorJob: OSupervisorJobpai não é cancelado quando ocorre uma exceção numa coroutine filha. Apenas a coroutine onde ocorreu a erro é cancelada. Isto é útil quando queres que o cancelamento de uma tarefa filha não afete as outras.CoroutineScoperaiz: Se a exceção atingir oCoroutineScoperaiz (por exemplo,GlobalScopeou um scope criado comCoroutineScopesemJob), ela é passada ao gestor global de exceçõesCoroutineExceptionHandler. Por padrão, se não houver um gestor registado, a exceção é registada emSystem.err.
-
Exceção controlada: Se a exceção for capturada com um bloco
try-catchdentro da coroutine, ela é tratada localmente, e a coroutine continua a sua execução após o blococatch, se possível. A exceção não se propaga para cima. -
Exceções relacionadas com cancelamento (por exemplo,
CancellationException): Estas exceções são especiais. São usadas para o mecanismo de cancelamento de coroutines e geralmente são ignoradas pela maioria dos gestores de exceções por padrão. Elas não causam uma falha fatal noJobpai por padrão. -
Exceções em
async: A coroutine lançada comasynccoloca a exceção no seuDeferred. A exceção só se propaga quando se chama.await()nesseDeferred. Até lá, a exceção está "oculta".
import kotlinx.coroutines.*
fun main() = runBlocking {
val scope = CoroutineScope(SupervisorJob())
scope.launch {
try {
println("Coroutine 1 iniciada")
delay(100)
throw RuntimeException("Algo correu mal na Coroutine 1")
} catch (e: Exception) {
println("Coroutine 1 capturou exceção: ${e.message}")
}
}
scope.launch {
println("Coroutine 2 iniciada")
delay(500)
println("Coroutine 2 terminada")
}
delay(1000) // Espera para ver a saída
scope.cancel() // Cancela o scope
}
Neste exemplo, a exceção na Coroutine 1 é capturada, e a Coroutine 2 continua a execução porque é usado SupervisorJob. Se fosse usado um Job normal, a exceção na Coroutine 1 levaria ao cancelamento da Coroutine 2.