Programação Reativa em Kotlin: biblioteca kotlinx.coroutines e Flow

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Programação Reativa em Kotlin: o poder do kotlinx.coroutines e Flow



Programação reativa é um paradigma focado no processamento assíncrono de fluxos de dados e na propagação de mudanças. No ecossistema Kotlin, a principal ferramenta para implementar padrões reativos é a biblioteca kotlinx.coroutines, mais especificamente seu componente Flow. Ao contrário do RxJava, o Flow é totalmente integrado com corrotinas, tornando o código mais conciso e seguro.



Conceitos fundamentais do Flow



Flow é um fluxo de dados assíncrono frio que emite valores sequencialmente. Ele suporta:

  • Fluxos frios — os dados começam a ser gerados apenas quando há um assinante (operador terminal).
  • Contexto de execução — o fluxo pode alternar entre diferentes dispatchers de corrotinas.
  • Cancelamento via corrotinas — o cancelamento da corrotina pai encerra automaticamente o Flow.


Instalação e configuração

Para usar o Flow, adicione a dependência no build.gradle.kts:

dependencies {    implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.1")}


Criação e consumo de Flow

Vamos criar um fluxo simples de números com atraso:

import kotlinx.coroutines.*import kotlinx.coroutines.flow.*

fun simpleFlow(): Flow<Int> = flow { for (i in 1..5) { delay(100) // simulação de trabalho assíncrono emit(i) // emite o valor }}

fun main() = runBlocking { simpleFlow().collect { value -> println("Recebido: $value") }}

Neste exemplo, flow { ... } cria um fluxo frio, e collect é o operador terminal que inicia a execução.



Transformação de dados com operadores

O Flow oferece um rico conjunto de operadores, semelhantes ao RxJava:

  • map — transforma cada valor.
  • filter — filtra valores por condição.
  • flatMapConcat — combina fluxos sequencialmente.
  • catch — trata exceções dentro do fluxo.

Exemplo com operadores:

fun transformFlow(): Flow<String> = flow {    emit("Kotlin")    emit("Java")    emit("Python")}.map { it.lowercase() } .filter { it.startsWith("k") }

fun main() = runBlocking { transformFlow().collect { println(it) } // Saída: kotlin}


Tratamento de erros e conclusão

O Flow permite tratar exceções elegantemente com catch e executar ações finais com onCompletion:

fun errorProneFlow(): Flow<Int> = flow {    emit(1)    emit(2)    throw RuntimeException("Erro!")    emit(3) // não será executado}

fun main() = runBlocking { errorProneFlow() .catch { e -> println("Erro capturado: ${e.message}") } .onCompletion { println("Fluxo concluído") } .collect { println(it) }}// Saída: 1, 2, Erro capturado: Erro!, Fluxo concluído


Fluxos quentes: StateFlow e SharedFlow

Ao contrário do Flow frio, StateFlow e SharedFlow são fluxos quentes que armazenam estado e podem ter vários assinantes.



StateFlow

Usado para armazenar e observar estado (por exemplo, em ViewModel):

class CounterViewModel {    private val _counter = MutableStateFlow(0)    val counter: StateFlow<Int> = _counter.asStateFlow()

fun increment() { _counter.value++ }}

// Em Activity ou FragmentlifecycleScope.launch { viewModel.counter.collect { value -> textView.text = "Contagem: $value" }}


SharedFlow

Adequado para

Recommendations