Kotlin Academy · Lektion

SupervisorJob kontra Job: isolera fel

Använd SupervisorJob för att hindra att ett barns fel avbryter syskonen.

Lektion 1 av 413 steg

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.

Gratis att börja

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

  1. SupervisorJob kontra Job: isolera fel
  2. CoroutineExceptionHandler: global hanterare för ofångade fel
  3. Exception-spridning med async/await
  4. Utforma motståndskraftiga coroutine-arkitekturer
← Tillbaka till Kotlin Academy