Kotlin Academy · Aula

catch e onCompletion: tratamento de erros em Flow

Capture exceções upstream e reaja a eventos de conclusão do fluxo.

Aula 2 de 413 etapas

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.

Grátis para começar

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

  1. Operadores de Flow: map, filter, transform e take
  2. catch e onCompletion: tratamento de erros em Flow
  3. combine e zip: mesclando vários Flows
  4. flowOn e buffer: contexto e contrapressão
← Voltar para Kotlin Academy