SupervisorJob vs Job: isolamento de falhas
Use SupervisorJob para impedir que a falha de uma corrotina filha cancele as irmãs.
SupervisorJob vs Job: isolamento de falhas é uma aula grátis de Kotlin Academy no CoddyKit. Esta é a aula 1 de 4. Você pode ler a aula completa abaixo gratuitamente — depois pratica ao vivo no navegador com um editor de código integrado e um tutor de IA 24/7. Faz parte do caminho de aprendizado de Kotlin Academy, e seu progresso é sincronizado entre a web e o app CoddyKit. O curso de Kotlin Academy inclui 4 aulas no total.
Propagação padrão de falhas de Job
Com um Job comum, a falha de um filho cancela o pai, que cancela todos os irmãos. Uma única falha derruba toda a hierarquia.
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}")
}
}Visão geral de SupervisorJob
SupervisorJob muda a regra: a falha de um filho NÃO cancela os irmãos nem o pai. Cada filho falha de forma independente.
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()
}Construtor supervisorScope
supervisorScope { } cria um escopo com um SupervisorJob como pai. Essa é a forma idiomática de executar filhos independentes.
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
}
}Capturando falhas de filhos
Com supervisorScope, cada filho trata sua própria exceção. As exceções não tratadas nos filhos devem ser capturadas individualmente por filho.
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 versus SupervisorJob ao criar um escopo
Passe SupervisorJob() ao criar um CoroutineScope para um serviço ou ViewModel que deva sobreviver a falhas individuais de filhos.
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 usa SupervisorJob
O viewModelScope do Android é baseado em um SupervisorJob. Uma inicialização que falhe não cancela as outras corrotinas do ViewModel.
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")
}Decomposição paralela com supervisorScope
Use supervisorScope + execução assíncrona para tarefas paralelas em que algumas possam falhar sem afetar as demais.
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) }
}Quando Usar uma Tarefa Regular
Use uma Job regular (coroutineScope) quando todos os filhos precisarem ter sucesso juntos — uma falha deve interromper o grupo. É como uma transação: tudo ou nada.
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}")
}
}Propagação de Exceções em supervisorScope
Em supervisorScope, uma exceção só se propaga para o escopo se escapar do nível superior do filho — ou seja, se não houver um bloco try-catch no filho. O pai não a recebe.
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 com SupervisorJob
Instale um CoroutineExceptionHandler em um escopo supervisor para registrar ou tratar falhas não capturadas dos filhos sem encerrar o escopo.
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()
}Resumo do Isolamento de Falhas
Tarefa: um filho falha → todos falham. SupervisorJob: os filhos falham de forma independente. Use um supervisor para serviços e ViewModels; use uma tarefa regular para grupos transacionais.
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") }Verificação Rápida
Qual escopo impede que a falha de um filho cancele seus irmãos?
Recapitulação
Tarefa: a falha se propaga para os irmãos. SupervisorJob/supervisorScope: as falhas ficam isoladas por filho. Use supervisorScope para tarefas paralelas independentes; use coroutineScope regular para grupos transacionais.
Perguntas Frequentes
A aula “SupervisorJob vs Job: isolamento de falhas” é grátis?
Sim — o texto completo de “SupervisorJob vs Job: isolamento de falhas” é grátis para ler aqui na web. Para praticá-la interativamente (um editor de código integrado e um tutor de IA 24/7) e desbloquear o restante do curso de Kotlin Academy, atualize para CoddyKit PRO. O curso de Kotlin Academy inclui 4 aulas no total.
O que vou aprender em “SupervisorJob vs Job: isolamento de falhas”?
Use SupervisorJob para impedir que a falha de uma corrotina filha cancele as irmãs. Você pratica Kotlin Academy com código prático que executa diretamente no navegador, e um tutor de IA 24/7 responde suas dúvidas enquanto trabalha na aula.
Preciso ter experiência prévia para começar Kotlin Academy?
Nenhuma experiência prévia é necessária. Kotlin Academy no CoddyKit é estruturado para alunos iniciantes até avançados, então você pode começar aqui ou desde o início e aprender no seu ritmo. Esta é a aula 1 de 4.
Quanto tempo leva a aula “SupervisorJob vs Job: isolamento de falhas”?
A maioria das aulas CoddyKit leva cerca de 5–10 minutos. Cada uma é compacta e interativa, então você faz progresso constante e retoma exatamente de onde parou entre web e app.
Posso escrever e executar código nesta aula de Kotlin Academy?
Sim. Cada aula de Kotlin Academy inclui um editor de código integrado, então você escreve e executa código real direto no navegador e recebe feedback de IA instantaneamente — nenhuma configuração local necessária.
Todas as aulas deste curso
- SupervisorJob vs Job: isolamento de falhas
- CoroutineExceptionHandler: manipulador global de exceções não capturadas
- Propagação de exceções em async/await
- Projetando arquiteturas resilientes de corrotinas