Co se stane s korutou, když dojde k výjimce?
sobes.tech AI
Odpověď od AI
Při výskytu výjimky uvnitř korutiny závisí způsob jejího zpracování na typu výjimky (a nastavení dispatcheru/kontextu).
-
Neřízená výjimka: Pokud je výjimka nezachycena uvnitř korutiny, propaguje se vzhůru po hierarchii korutin až k nejbližšímu rodičovskému
Job(neboCoroutineScope). Chování závisí na typuJob:Job: Ve výchozím nastavení, pokud dojde k výjimce v podřízené korutině, rodičovskýJobje zrušen, což vede ke zrušení všech jeho ostatních podřízených korutin. Výjimka je přenášena výše.SupervisorJob: RodičovskýSupervisorJobnení zrušen při výskytu výjimky v podřízené korutině. Zrušena je pouze samotná korutina, ve které došlo k výjimce. To je užitečné, když je třeba, aby zrušení jedné podřízené úlohy neovlivnilo ostatní.- Kořenový
CoroutineScope: Pokud výjimka dosáhne kořenovéhoCoroutineScope(napříkladGlobalScopenebo scope vytvořený pomocíCoroutineScopebezJob), je předána globálnímu zpracovateli výjimekCoroutineExceptionHandler. Ve výchozím nastavení, pokud není registrován žádný zpracovatel, je výjimka zaznamenána vSystem.err.
-
Zachycená výjimka: Pokud je výjimka zachycena pomocí bloku
try-catchuvnitř korutiny, je zpracována lokálně a korutina pokračuje v provádění po blokucatch, pokud je to možné. Výjimka se nepřenáší výše. -
Výjimky související s zrušením (například
CancellationException): Tyto výjimky jsou speciální. Používají se pro mechanismus zrušení korutin a obvykle jsou ignorovány většinou zpracovatelů výjimek ve výchozím nastavení. Nevedou k fatálnímu selhání rodičovskéhoJobve výchozím nastavení. -
Výjimky v
async: Korutina spuštěná pomocíasyncumisťuje výjimku do svéhoDeferred. Výjimka je přenášena pouze při volání.await()na tomtoDeferred. Do té doby je výjimka "skryta".
import kotlinx.coroutines.*
fun main() = runBlocking {
val scope = CoroutineScope(SupervisorJob())
scope.launch {
try {
println("Korutina 1 začala")
delay(100)
throw RuntimeException("Něco se pokazilo v Korutině 1")
} catch (e: Exception) {
println("Zachycena výjimka v Korutině 1: ${e.message}")
}
}
scope.launch {
println("Korutina 2 začala")
delay(500)
println("Korutina 2 dokončena")
}
delay(1000) // Čekáme, aby se zobrazil výstup
scope.cancel() // Zrušíme scope
}
V tomto příkladu je výjimka v Korutině 1 zachycena a Korutina 2 pokračuje v provádění, protože je použit SupervisorJob. Pokud by byl použit místo toho běžný Job, výjimka v Korutině 1 by vedla ke zrušení Korutiny 2.