---
title: "Emit em Kotlin: O que É e Como Funciona | Kotlin Brasil"
url: "https://kotlin.dev.br/glossario/emit/"
markdown_url: "https://kotlin.dev.br/glossario/emit.MD"
description: "Entenda o que é a função emit em Kotlin Flow, como emitir valores em streams reativos assíncronos com coroutines."
date: "2025-08-07"
author: "Karina Melo"
---

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

Entenda o que é a função emit em Kotlin Flow, como emitir valores em streams reativos assíncronos com coroutines.


## O que é emit em Kotlin?

A função **`emit`** é o mecanismo principal para **enviar valores** dentro de um `Flow` em Kotlin. Quando você cria um Flow usando o builder `flow { }`, cada chamada a `emit(valor)` envia um novo valor para o coletor (quem esta consumindo o Flow).

Pense no `emit` como o momento em que você coloca um item na esteira de producao. Do outro lado, o `collect` pega cada item conforme ele chega. Essa dinâmica de produtor-consumidor é a essencia do Flow.

### Sintaxe básica

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

fun numeros(): Flow<Int> = flow {
    emit(1)
    emit(2)
    emit(3)
}

fun main() = runBlocking {
    numeros().collect { valor ->
        println("Recebido: $valor")
    }
}
// Saida:
// Recebido: 1
// Recebido: 2
// Recebido: 3
```

Cada `emit` e uma função `suspend`, o que significa que ela pode pausar a execução do produtor até que o consumidor esteja pronto para receber o proximo valor.

### emit e uma função suspend

O fato de `emit` ser `suspend` e fundamental para o comportamento do Flow:

```kotlin
fun dadosComDelay(): Flow<String> = flow {
    emit("Carregando...")
    delay(1000)
    emit("Dados parciais")
    delay(1000)
    emit("Dados completos")
}

fun main() = runBlocking {
    dadosComDelay().collect { status ->
        println("$status - ${System.currentTimeMillis()}")
    }
}
```

O produtor pode suspender entre emissoes (usando `delay` ou outras funções suspend), e o consumidor recebe cada valor conforme ele e emitido. Isso cria um fluxo natural de dados ao longo do tempo.

### Emitindo em loops

Um padrão comum e emitir valores dentro de um loop:

```kotlin
fun contagem(de: Int, ate: Int): Flow<Int> = flow {
    for (i in de..ate) {
        delay(500)
        emit(i)
    }
}

fun fibonacci(): Flow<Long> = flow {
    var a = 0L
    var b = 1L
    while (true) {
        emit(a)
        val temp = a + b
        a = b
        b = temp
    }
}

fun main() = runBlocking {
    // Pegar os 10 primeiros Fibonacci
    fibonacci().take(10).collect { println(it) }
}
```

O Flow e lazy: o loop infinito em `fibonacci()` não e um problema porque `take(10)` cancela o Flow apos coletar 10 valores.

### Emitindo a partir de fontes externas

O `emit` pode ser chamado apos receber dados de qualquer fonte:

```kotlin
fun monitorarArquivo(caminho: String): Flow<String> = flow {
    val arquivo = java.io.File(caminho)
    var ultimaModificacao = 0L

    while (true) {
        val modificacao = arquivo.lastModified()
        if (modificacao != ultimaModificacao) {
            ultimaModificacao = modificacao
            emit(arquivo.readText())
        }
        delay(1000)
    }
}

fun leiturasDeSensor(): Flow<Double> = flow {
    val random = java.util.Random()
    while (true) {
        val leitura = 20.0 + random.nextDouble() * 10.0
        emit(leitura)
        delay(500)
    }
}
```

### Restricoes do emit

O `emit` tem uma restricao importante: **não pode ser chamado de um contexto concorrente**. Dentro de um `flow { }`, você não pode emitir de outra coroutine:

```kotlin
// ERRADO: emit de contexto concorrente
fun fluxoErrado(): Flow<Int> = flow {
    coroutineScope {
        launch {
            emit(1) // IllegalStateException em tempo de execucao!
        }
    }
}

// CORRETO: usar channelFlow para emissao concorrente
fun fluxoConcorrente(): Flow<Int> = channelFlow {
    launch {
        send(1) // OK: channelFlow suporta concorrência
    }
    launch {
        send(2)
    }
}
```

Se você precisa emitir valores de múltiplas coroutines, use `channelFlow` com `send` em vez de `flow` com `emit`.

### emit com transformacoes

Operadores como `transform` permitem emitir múltiplos valores para cada valor de entrada:

```kotlin
fun main() = runBlocking {
    val numeros = flowOf(1, 2, 3)

    numeros.transform { valor ->
        emit("Processando $valor...")
        delay(300)
        emit("Resultado: ${valor * valor}")
    }.collect { println(it) }
}
// Saida:
// Processando 1...
// Resultado: 1
// Processando 2...
// Resultado: 4
// Processando 3...
// Resultado: 9
```

O operador `transform` e a base sobre a qual `map` e `filter` são construidos. Ele da liberdade total sobre quantos valores emitir para cada valor recebido.

### Backpressure e emit

O `emit` naturalmente implementa backpressure. Se o coletor for mais lento que o produtor, o `emit` suspende até que o coletor esteja pronto:

```kotlin
fun produtorRapido(): Flow<Int> = flow {
    for (i in 1..5) {
        println("Emitindo $i")
        emit(i)
    }
}

fun main() = runBlocking {
    produtorRapido().collect { valor ->
        delay(1000) // Coletor lento
        println("Coletado: $valor")
    }
}
// A emissao espera o coletor processar antes de continuar
```

Para cenários onde você quer descartar valores ou usar buffer, existem operadores como `buffer`, `conflate` e `collectLatest`.

### Quando usar emit

- **Producao de dados sob demanda**: quando os dados são gerados dinamicamente e precisam ser consumidos um por vez.
- **Streams de eventos**: monitoramento de arquivos, sensores, WebSockets.
- **Transformacoes complexas**: quando você precisa emitir múltiplos valores derivados de um único valor de entrada.
- **Conversao de callbacks para Flow**: dentro de `callbackFlow`, você usa `trySend` (similar ao emit) para converter APIs baseadas em callback para Flow.

### Casos de Uso no Mundo Real

1. **Monitoramento de dados em tempo real**: aplicações que exibem dashboards com metricas ao vivo (preco de acoes, temperatura de servidores, status de sistemas) utilizam `emit` dentro de loops com delay para publicar atualizações periodicas. O Flow gerenciado com `emit` permite que a UI reaja a cada novo valor sem polling manual.

2. **Upload de arquivos com progresso**: durante o upload de arquivos grandes, o `emit` e usado para publicar o percentual de progresso. Um Flow emite valores de 0 a 100 conforme os chunks sao enviados, permitindo que a camada de apresentação atualize uma barra de progresso de forma reativa.

3. **paginação de APIs**: ao buscar dados paginados de uma API REST, o `emit` publica cada pagina de resultados conforme ela e carregada. O consumidor pode processar e exibir os dados incrementalmente sem esperar que todas as paginas sejam carregadas.

4. **Conversao de callbacks legados para Flow**: em projetos que migram de APIs baseadas em callback (como listeners do Firebase ou eventos de sensores do Android), o `emit` (via `callbackFlow` e `trySend`) e o mecanismo que transforma esses callbacks em streams reativos compativeis com a arquitetura moderna baseada em coroutines.

### Boas Praticas

- Mantenha a lógica de emissao simples e focada na producao de dados. Transformacoes complexas devem ser feitas com operadores do Flow (`map`, `filter`, `transform`) em vez de lógica condicional elaborada antes de cada `emit`.
- Use `channelFlow` com `send` em vez de `flow` com `emit` quando precisar emitir valores de múltiplas coroutines concorrentes. Tentar emitir de contextos concorrentes dentro de `flow {}` causa exceção em tempo de execução.
- Trate exceções que possam ocorrer antes do `emit` usando o operador `catch` no pipeline do Flow, em vez de try-catch dentro do builder. Isso mantém a separação entre producao e tratamento de erros.
- Ao emitir valores em loops infinitos (sensores, polling), sempre inclua um mecanismo de cancelamento cooperativo. O Flow já e cancelavel por natureza, mas certifique-se de que operações bloqueantes sejam interruptiveis.
- Evite efeitos colaterais dentro do builder `flow {}` que não estejam diretamente relacionados a producao de dados. Use o operador `onEach` no lado do consumo para acoes como logging e analytics.

### Perguntas Frequentes

**P: Posso chamar emit de dentro de uma coroutine lancada com launch ou async?**
R: Nao, dentro de um builder `flow {}`. O `emit` exige que a emissao seja sequencial e no mesmo contexto da coroutine do Flow. Se você precisa emitir de contextos concorrentes, use `channelFlow` com a função `send` em vez de `flow` com `emit`.

**P: O que acontece se o coletor for mais lento que o produtor?**
R: O `emit` implementa backpressure naturalmente: ele suspende a execução do produtor até que o coletor termine de processar o valor anterior. Para cenários onde você quer alterar esse comportamento, use operadores como `buffer` (para adicionar um buffer intermediario), `conflate` (para descartar valores intermediarios) ou `collectLatest` (para cancelar o processamento anterior quando um novo valor chega).

**P: Qual a diferenca entre emit e trySend em callbackFlow?**
R: O `emit` e uma função suspend usada dentro de `flow {}`, enquanto `trySend` e uma função não-suspend usada dentro de `callbackFlow {}`. O `trySend` e necessário em callbacks porque callbacks tradicionais não sao funções suspend. O `trySend` retorna um resultado indicando se o envio foi bem-sucedido, sem suspender a thread.

**P: Posso emitir null em um Flow?**
R: Sim, desde que o tipo do Flow permita nulos. Um `Flow<String?>` aceita `emit(null)` normalmente. O coletor recebera o valor null como qualquer outro valor emitido.

### Erros comuns

1. **Chamar emit fora do flow builder**: `emit` só pode ser chamado dentro do escopo do builder `flow { }` ou dentro de operadores como `transform`.

2. **Emitir de contexto concorrente**: usar `launch` ou `async` dentro de `flow { }` e tentar emitir. Use `channelFlow` para isso.

3. **Esquecer que emit e suspend**: tratar emit como uma operação instantanea quando na verdade ela pode suspender se o coletor estiver ocupado.

4. **Nao tratar exceções**: se uma exceção ocorre antes do emit, os valores já emitidos foram processados, mas os restantes serao perdidos. Use `catch` no Flow para tratamento adequado.

5. **Confundir emit com send**: `emit` e para `flow { }`, `send` e para `channelFlow { }` e channels. Usar um no contexto do outro causa erro de compilação.

### callbackFlow e trySend

Para converter APIs baseadas em callback para Flow, use `callbackFlow` com `trySend`:

```kotlin
fun eventosDeClique(botao: Botao): Flow<Unit> = callbackFlow {
    val listener = object : OnClickListener {
        override fun onClick() {
            trySend(Unit)
        }
    }
    botao.adicionarListener(listener)
    awaitClose { botao.removerListener(listener) }
}
```

### Termos relacionados

- **Flow**: o tipo de stream reativo do Kotlin onde `emit` e a função principal de producao.
- **collect**: a função terminal que consome os valores emitidos por um Flow.
- **channelFlow**: builder de Flow que suporta emissao concorrente usando `send`.
- **transform**: operador que permite emitir múltiplos valores para cada valor de entrada.
- **Coroutine**: contexto de execução assíncrono onde Flows operam.
- **suspend**: modificador que permite que `emit` pause a execução quando necessário.

O `emit` e o coracao do sistema de Flows em Kotlin. Entender como ele funciona, suas restricoes de concorrência e sua relação com backpressure e essencial para construir pipelines de dados reativos eficientes e corretos.
