O que é Flow em Kotlin?

O Flow é o mecanismo do Kotlin para trabalhar com streams de dados assíncronos. Enquanto uma função suspend retorna um único valor, um Flow pode emitir múltiplos valores ao longo do tempo, um de cada vez.

Pense no Flow como uma torneira: os dados vão saindo conforme são produzidos, e você consome na hora que quiser.

Sintaxe básica

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

fun contagem(): Flow<Int> = flow {
    for (i in 1..5) {
        delay(500)
        emit(i)
    }
}

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

O flow { } cria o produtor, o emit() envia cada valor e o collect consome. Simples assim.

Flow é “cold”

Uma característica importante: o Flow é cold, ou seja, ele só começa a produzir dados quando alguém chama collect. Se ninguém coletar, nada acontece.

val meuFlow = flow {
    println("Flow iniciado!") // Só executa quando alguém coletar
    emit(1)
    emit(2)
}

Operadores úteis

Flow vem com vários operadores pra transformar e filtrar dados:

fun main() = runBlocking {
    (1..10).asFlow()
        .filter { it % 2 == 0 }
        .map { it * it }
        .collect { println(it) }
    // 4, 16, 36, 64, 100
}

Alguns operadores mais usados:

  • map — transforma cada valor
  • filter — filtra valores
  • take — pega os N primeiros
  • onEach — executa ação em cada valor
  • catch — trata erros no fluxo

Exemplo prático: atualizações em tempo real

fun atualizacoesDePrecо(): Flow<Double> = flow {
    val precos = listOf(45.50, 46.20, 44.80, 47.10)
    for (preco in precos) {
        delay(1000)
        emit(preco)
    }
}

fun main() = runBlocking {
    atualizacoesDePrecо().collect { preco ->
        println("Preço atual: R$ $preco")
    }
}

Flow é ideal para dados que chegam aos poucos: eventos de UI, atualizações de banco de dados, respostas de WebSocket e qualquer cenário onde você precisa reagir a mudanças contínuas.