---
title: "Flow em Kotlin: O que É e Como Funciona | Kotlin Brasil"
url: "https://kotlin.dev.br/glossario/flow/"
markdown_url: "https://kotlin.dev.br/glossario/flow.MD"
description: "Entenda o que é Flow em Kotlin, como emitir e coletar streams de dados assíncronos usando coroutines."
date: "2026-02-06"
author: "Karina Melo"
---

# Flow em Kotlin: O que É e Como Funciona | Kotlin Brasil

Entenda o que é Flow em Kotlin, como emitir e coletar streams de dados assíncronos usando coroutines.


## 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

```kotlin
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.

```kotlin
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:

```kotlin
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

```kotlin
fun atualizacoesDePreco(): 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 {
    atualizacoesDePreco().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.

### StateFlow e SharedFlow

Além do `Flow` tradicional (cold), Kotlin oferece variantes **hot** que mantêm estado ou compartilham emissões entre múltiplos coletores:

```kotlin
import kotlinx.coroutines.flow.*

// StateFlow: mantém o último valor emitido
val _contador = MutableStateFlow(0)
val contador: StateFlow<Int> = _contador.asStateFlow()

// SharedFlow: broadcast para múltiplos coletores
val _eventos = MutableSharedFlow<String>()
val eventos: SharedFlow<String> = _eventos.asSharedFlow()
```

O `StateFlow` é muito usado em arquiteturas como MVVM no Android, substituindo o `LiveData` com uma API baseada em coroutines. Já o `SharedFlow` é ideal para eventos que não devem ser repetidos, como navegação ou exibição de mensagens.

### Combinando Flows

Você pode combinar múltiplos Flows para criar fluxos de dados mais complexos:

```kotlin
fun main() = runBlocking {
    val nomes = flowOf("Ana", "Bruno", "Carla")
    val idades = flowOf(25, 30, 28)

    nomes.zip(idades) { nome, idade ->
        "$nome tem $idade anos"
    }.collect { println(it) }
    // Ana tem 25 anos
    // Bruno tem 30 anos
    // Carla tem 28 anos
}
```

O operador `combine` é outra opção: ele re-emite sempre que qualquer um dos Flows emite um novo valor, usando o último valor disponível de cada um.

### Casos de Uso no Mundo Real

- **Atualizações de interface no Android**: usar `StateFlow` no ViewModel para expor o estado da tela e coletar no Fragment ou Composable, garantindo que a UI sempre reflita o estado mais recente.
- **Busca com debounce**: capturar o texto digitado pelo usuário como um Flow e aplicar `debounce(300)` seguido de `distinctUntilChanged()` e `flatMapLatest` para realizar buscas sem sobrecarregar a API.
- **Monitoramento de conexão de rede**: criar um Flow que emite o status de conectividade do dispositivo usando callbacks do sistema, permitindo que a aplicação reaja automaticamente a mudanças de rede.
- **Leitura contínua de sensores ou dados IoT**: usar Flow para modelar streams de dados de sensores como temperatura, localização GPS ou dados de dispositivos Bluetooth, processando cada leitura conforme ela chega.

### Boas Práticas

- Prefira expor `StateFlow` ou `SharedFlow` como tipos imutáveis na API pública e manter o `MutableStateFlow` ou `MutableSharedFlow` como privado.
- Use o operador `catch` para tratar erros dentro do pipeline do Flow em vez de envolver o `collect` em um bloco try-catch.
- Utilize `flowOn(Dispatchers.IO)` para mover a produção de dados para uma thread de IO, mantendo a coleta na thread principal quando necessário.
- Evite coletar Flows diretamente em `GlobalScope`. No Android, prefira `lifecycleScope` ou `repeatOnLifecycle` para evitar vazamentos de memória.
- Use `stateIn` e `shareIn` para converter Flows cold em hot quando múltiplos consumidores precisam do mesmo fluxo de dados.

### Erros Comuns

- **Coletar o mesmo Flow cold múltiplas vezes sem perceber**: cada chamada a `collect` reinicia a produção do Flow. Se isso não é o comportamento desejado, converta para `SharedFlow` com `shareIn`.
- **Esquecer que `collect` é uma função suspensa**: tentar chamar `collect` fora de uma coroutine causa erro de compilação. Sempre colete dentro de um escopo de coroutine.
- **Bloquear dentro de um `flow { }`**: usar operações bloqueantes como `Thread.sleep()` dentro do builder `flow` em vez de `delay()` trava a coroutine e anula os benefícios da abordagem assíncrona.
- **Não tratar erros no pipeline**: se uma exceção ocorre dentro de um Flow e não é capturada com `catch`, ela se propaga para o coletor e pode derrubar a coroutine inteira.
- **Confundir StateFlow com LiveData**: embora ambos mantenham o último valor, `StateFlow` requer coleta em coroutines e não é lifecycle-aware por padrão. No Android, combine com `repeatOnLifecycle`.

### Perguntas Frequentes

**Qual a diferença entre Flow e Sequence em Kotlin?** `Sequence` é síncrono e processa elementos sob demanda na mesma thread. `Flow` é assíncrono e trabalha com coroutines, permitindo operações suspensas como chamadas de rede e delays entre emissões.

**Quando devo usar StateFlow em vez de Flow?** Use `StateFlow` quando precisa manter o último valor emitido e compartilhar entre múltiplos coletores, como o estado de uma tela. Use `Flow` quando os dados são produzidos sob demanda e cada coletor deve receber seu próprio fluxo independente.

**Flow substitui RxJava?** Flow cobre a grande maioria dos casos de uso do RxJava para projetos Kotlin, com a vantagem de integração nativa com coroutines. Para projetos novos em Kotlin, Flow é a escolha recomendada.

**Posso usar Flow sem coroutines?** Não. Flow faz parte do pacote `kotlinx.coroutines.flow` e depende de coroutines para funcionar. A coleta de um Flow sempre acontece dentro de uma função suspensa.

### Termos Relacionados

- [Coroutine](/glossario/coroutine) — mecanismo de concorrência que sustenta o funcionamento do Flow
- [Suspend](/glossario/suspend) — modificador que permite funções assíncronas usadas dentro de Flows
- [Lambda](/glossario/lambda) — funções anônimas usadas nos operadores de Flow como `map` e `filter`
- [Higher-Order Function](/glossario/higher-order-function) — padrão de funções que recebem outras funções, base dos operadores de Flow
