catch e onCompletion: tratamento de erros em Flow
Capture exceções upstream e reaja a eventos de conclusão do fluxo.
catch e onCompletion: tratamento de erros em Flow é uma aula grátis de Kotlin Academy no CoddyKit. Esta é a aula 2 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.
Noções básicas sobre exceções em fluxos
As exceções em um fluxo o encerram. Sem tratamento, a exceção se propaga para o coletor e o fluxo termina.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
try {
flow {
emit(1)
throw RuntimeException("stream error")
emit(2)
}.collect { println(it) }
} catch (e: Exception) {
println("Caught: ${e.message}")
}
}Operador de captura
catch trata as exceções do fluxo a montante e pode emitir valores alternativos ou relançar a exceção. Ele não captura exceções lançadas pelo próprio coletor.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
flow {
emit(1)
throw RuntimeException("oops")
}.catch { e ->
println("Caught: ${e.message}")
emit(-1) // fallback value
}.collect { println(it) } // 1, then -1
}catch trata apenas o fluxo a montante
catch intercepta apenas exceções do construtor do fluxo e dos operadores a montante — não da lambda de collect.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
try {
flowOf(1, 2, 3)
.catch { e -> println("upstream: ${e.message}") }
.collect {
if (it == 2) throw RuntimeException("collector error") // not caught by catch
println(it)
}
} catch (e: Exception) {
println("Collector exception: ${e.message}")
}
}Relançamento durante a captura
Você pode inspecionar a exceção e relançar seletivamente aquelas que não consegue tratar.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
try {
flow {
emit(1)
throw IllegalStateException("state error")
}.catch { e ->
if (e is RuntimeException) { emit(-1); return@catch }
throw e // rethrow unknown exceptions
}.collect { println(it) }
} catch (e: Exception) {
println("Rethrown: ${e.message}")
}
}Operador onCompletion
onCompletion é executado quando o fluxo termina — normalmente ou com uma exceção. Seu parâmetro cause não é nulo em caso de falha.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
flowOf(1, 2, 3)
.onCompletion { cause ->
if (cause == null) println("Completed normally")
else println("Failed: ${cause.message}")
}
.collect { println(it) }
}onCompletion em caso de erro
onCompletion é acionado mesmo quando ocorre uma exceção a montante. Ele recebe a exceção como cause, mas não a suprime — a exceção ainda se propaga.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
try {
flow {
emit(1)
throw RuntimeException("error")
}.onCompletion { cause ->
println("onCompletion cause=${cause?.message}")
}.collect { println(it) }
} catch (e: Exception) {
println("outer catch: ${e.message}")
}
}Combinando catch e onCompletion
Use catch para recuperar-se e emitir valores alternativos; depois, use onCompletion para registrar informações ou liberar recursos independentemente do resultado.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
flow {
emit("ok")
throw RuntimeException("network error")
}.catch { e ->
emit("fallback") // recover
}.onCompletion {
println("Stream done — release resources")
}.collect { println(it) }
}Operador retry
retry(n) { ... } reinscreve-se no fluxo a montante quando ocorre uma exceção, até n vezes.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
var attempt = 0
fun unstableFlow() = flow {
attempt++
if (attempt < 3) throw RuntimeException("attempt $attempt failed")
emit("success on attempt $attempt")
}
fun main() = runBlocking {
unstableFlow()
.retry(3) { e -> println("retrying: ${e.message}"); true }
.collect { println(it) }
}retryWhen para lógica personalizada
retryWhen fornece a exceção e o número de tentativas para que você possa adicionar um atraso progressivo ou filtrar quais exceções acionam uma nova tentativa.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
var n = 0
flow {
if (n++ < 2) throw IOException("IO error")
emit("done")
}.retryWhen { cause, attempt ->
cause is IOException && attempt < 3
}.collect { println(it) }
}Operador onStart
onStart é executado antes da primeira emissão — é útil para mostrar estados de carregamento ou inicializar recursos antes da chegada dos dados.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
fun main() = runBlocking {
flowOf("data")
.onStart { emit("Loading...") }
.onCompletion { emit("Done") }
.collect { println(it) }
}Tratamento de erros em chamadas reais à interface de programação
Envolva os fluxos do repositório com catch para mapear exceções para erros do domínio e com onCompletion para ocultar os indicadores de carregamento.
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
sealed class State { object Loading : State(); data class Data(val v: String) : State(); data class Error(val msg: String) : State() }
fun apiFlow(): Flow<String> = flow { delay(50); emit("response") }
fun uiFlow(): Flow<State> = apiFlow()
.map { State.Data(it) as State }
.onStart { emit(State.Loading) }
.catch { e -> emit(State.Error(e.message ?: "unknown")) }
fun main() = runBlocking { uiFlow().collect { println(it) } }Verificação rápida
Qual é a principal limitação do operador catch?
Recapitulação
captura trata exceções upstream e pode emitir valores alternativos. onCompletion sempre é executado (em caso normal ou de erro) para limpeza ou registro. Combine-os com nova tentativa/nova tentativa quando para obter cadeias de fluxos resilientes.
Aprenda Kotlin com um tutor de IA — grátis
Escreva e execute código real no seu navegador, obtenha ajuda instantânea de um tutor de IA 24/7 e continue de onde parou na web ou no app.
- Cursos
- 51
- Aulas
- 203
Perguntas Frequentes
A aula “catch e onCompletion: tratamento de erros em Flow” é grátis?
Sim — o texto completo de “catch e onCompletion: tratamento de erros em Flow” é 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 “catch e onCompletion: tratamento de erros em Flow”?
Capture exceções upstream e reaja a eventos de conclusão do fluxo. 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 2 de 4.
Quanto tempo leva a aula “catch e onCompletion: tratamento de erros em Flow”?
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
- Operadores de Flow: map, filter, transform e take
- catch e onCompletion: tratamento de erros em Flow
- combine e zip: mesclando vários Flows
- flowOn e buffer: contexto e contrapressão