SupervisorJob kontra Job: isolera fel
Använd SupervisorJob för att hindra att ett barns fel avbryter syskonen.
SupervisorJob kontra Job: isolera fel är en gratis lektion i Kotlin Academy på CoddyKit. Detta är lektion 1 av 4. Du kan läsa vilka 3 lektioner som helst i den här lärvägen kostnadsfritt i sin helhet – därefter låser CoddyKit PRO upp alla lektioner, plus praktisk övning med en inbyggd kodredigerare och en AI-lärare dygnet runt. Den ingår i lärvägen för Kotlin Academy, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i Kotlin Academy innehåller totalt 4 lektioner.
Standardpropagering av fel med Job
Med en vanlig Job avbryter ett fel i ett underordnat jobb det överordnade jobbet, som i sin tur avbryter alla syskon. Ett enda fel fäller hela hierarkin.
import kotlinx.coroutines.*
fun main() = runBlocking {
try {
coroutineScope {
launch { delay(50); throw RuntimeException("child 1 failed") }
launch { delay(1000); println("child 2 — never prints") }
}
} catch (e: RuntimeException) {
println("Caught: ${e.message}")
}
}Översikt över SupervisorJob
SupervisorJob ändrar regeln: ett fel i ett underordnat jobb avbryter INTE syskonen eller det överordnade jobbet. Varje underordnat jobb misslyckas oberoende av de andra.
import kotlinx.coroutines.*
fun main() = runBlocking {
val supervisor = SupervisorJob()
val scope = CoroutineScope(coroutineContext + supervisor)
scope.launch { throw RuntimeException("child 1 failed") }
scope.launch { delay(100); println("child 2 still runs") }
delay(200)
supervisor.cancel()
}supervisorScope-byggare
supervisorScope { } skapar ett scope med en SupervisorJob som överordnat jobb. Det är det idiomatiska sättet att köra oberoende underordnade coroutiner.
import kotlinx.coroutines.*
fun main() = runBlocking {
supervisorScope {
val job1 = launch {
throw RuntimeException("job1 failed")
}
val job2 = launch {
delay(100)
println("job2 succeeded")
}
job1.join() // wait for job1 (it failed)
job2.join() // job2 is unaffected
}
}Fånga fel i underordnade coroutiner
Med supervisorScope hanterar varje underordnad coroutine sitt eget undantag. Undantag i underordnade coroutiner som inte hanteras måste fångas för varje underordnad coroutine.
import kotlinx.coroutines.*
fun main() = runBlocking {
supervisorScope {
val result = async {
delay(50)
throw RuntimeException("async failed")
}
try {
result.await()
} catch (e: RuntimeException) {
println("Caught from async: ${e.message}")
}
println("Scope continues")
}
}Job kontra SupervisorJob när scope skapas
Skicka med SupervisorJob() när du skapar ett CoroutineScope för en tjänst eller ViewModel som ska överleva enskilda fel i underordnade coroutiner.
import kotlinx.coroutines.*
class MyService {
private val scope = CoroutineScope(Dispatchers.Default + SupervisorJob())
fun startTask(name: String) {
scope.launch {
if (name == "fail") throw RuntimeException("$name failed")
println("$name done")
}
}
fun stop() = scope.cancel()
}
fun main() = runBlocking {
val svc = MyService()
svc.startTask("fail")
svc.startTask("ok")
delay(100)
svc.stop()
}viewModelScope använder SupervisorJob
Androids viewModelScope bygger på en SupervisorJob. En misslyckad launch avbryter inte ViewModelens övriga coroutiner.
import kotlinx.coroutines.*
// Android ViewModel internals:
// val viewModelScope = CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate)
// Each launch is independent — one failure doesn't crash the ViewModel
fun main() = runBlocking {
println("viewModelScope = SupervisorJob + Main")
}Parallell uppdelning med supervisorScope
Använd supervisorScope + async för parallella uppgifter där vissa kan misslyckas utan att påverka de andra.
import kotlinx.coroutines.*
fun main() = runBlocking {
val results = supervisorScope {
val a = async { delay(50); "result-A" }
val b = async { throw RuntimeException("B failed") }
val c = async { delay(30); "result-C" }
listOf(
runCatching { a.await() },
runCatching { b.await() },
runCatching { c.await() }
)
}
results.forEach { println(it) }
}När ska en vanlig Job användas
Använd en vanlig Job (coroutineScope) när alla barn måste lyckas tillsammans – ett misslyckande ska avbryta hela gruppen. Som en transaktion: allt eller inget.
import kotlinx.coroutines.*
fun main() = runBlocking {
try {
coroutineScope { // regular Job
val a = async { delay(50); "A" }
val b = async { throw RuntimeException("B failed") }
println(a.await())
println(b.await()) // throws — cancels a too
}
} catch (e: RuntimeException) {
println("Transaction failed: ${e.message}")
}
}Undantagets spridning i supervisorScope
I supervisorScope sprids ett undantag till scope endast om det lämnar barnets toppnivå, det vill säga om barnet saknar try-catch. Den överordnade korutinen ser det inte.
import kotlinx.coroutines.*
fun main() = runBlocking {
supervisorScope {
// Exception caught inside child — scope unaffected
launch {
try { throw RuntimeException("handled") }
catch (e: Exception) { println("Child caught: ${e.message}") }
}
delay(100)
println("Scope survived")
}
}CoroutineExceptionHandler med SupervisorJob
Installera en CoroutineExceptionHandler i ett supervisor-scope för att logga eller reagera på ohanterade fel i barnkorutiner utan att få scopet att krascha.
import kotlinx.coroutines.*
fun main() = runBlocking {
val handler = CoroutineExceptionHandler { _, e ->
println("Uncaught: ${e.message}")
}
val scope = CoroutineScope(SupervisorJob() + handler)
scope.launch { throw RuntimeException("unhandled failure") }
scope.launch { delay(100); println("still running") }
delay(200)
scope.cancel()
}Sammanfattning av felisolering
Job: ett barn misslyckas → alla misslyckas. SupervisorJob: barn misslyckas oberoende av varandra. Använd supervisor för tjänster och ViewModels, och vanlig Job för transaktionella grupper.
import kotlinx.coroutines.*
// Decision table:
// coroutineScope { } -> Job: all-or-nothing
// supervisorScope { } -> SupervisorJob: independent failures
// CoroutineScope(SupervisorJob()) -> long-lived service
fun main() = runBlocking { println("Pick the right job for the right scope") }Snabbkontroll
Vilket scope hindrar ett fel i ett barn från att avbryta dess syskon?
Sammanfattning
Job: ett fel sprids till syskonen. SupervisorJob/supervisorScope: fel isoleras per barn. Använd supervisorScope för parallella, oberoende uppgifter och vanlig coroutineScope för transaktionella grupper.
Lär dig Kotlin med en AI-lärare – gratis
Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.
- Kurser
- 51
- Lektioner
- 203
Vanliga frågor
Är lektionen ”SupervisorJob kontra Job: isolera fel” gratis?
Ja – du kan läsa vilka 3 lektioner som helst i lärvägen Kotlin Academy, inklusive ”SupervisorJob kontra Job: isolera fel”, kostnadsfritt i sin helhet här på webben. Därefter låser CoddyKit PRO upp alla lektioner, plus interaktiv övning med en inbyggd kodredigerare och en AI-lärare dygnet runt. Kursen i Kotlin Academy innehåller totalt 4 lektioner.
Vad lär jag mig i ”SupervisorJob kontra Job: isolera fel”?
Använd SupervisorJob för att hindra att ett barns fel avbryter syskonen. Ni övar på Kotlin Academy med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.
Behöver jag någon erfarenhet för att börja lära mig Kotlin Academy?
Du behöver inga förkunskaper. Utbildningen i Kotlin Academy på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 1 av 4.
Hur lång tid tar lektionen ”SupervisorJob kontra Job: isolera fel”?
De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.
Kan jag skriva och köra kod i den här Kotlin Academy-lektionen?
Ja. Varje Kotlin Academy-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.
Alla lektioner i den här kursen
- SupervisorJob kontra Job: isolera fel
- CoroutineExceptionHandler: global hanterare för ofångade fel
- Exception-spridning med async/await
- Utforma motståndskraftiga coroutine-arkitekturer