DEV Community

Cover image for Otimizando Programação Assíncrona com Fluxos no Kotlin: Introdução ao `Flow`
Alan Gomes for Comunidade Dev Space

Posted on

Otimizando Programação Assíncrona com Fluxos no Kotlin: Introdução ao `Flow`

1 – Introdução

À medida que a complexidade das aplicações cresce, lidar com múltiplos eventos assíncronos em tempo real se torna essencial. Para isso, o Kotlin oferece uma poderosa ferramenta chamada Flow, que simplifica o gerenciamento de fluxos de dados assíncronos.

Neste artigo, exploraremos:

  • O que é um Flow e como ele difere de outras abordagens como suspend e async.
  • Casos reais de uso de Flow.
  • Ferramentas como o Turbine para testar fluxos de dados.

2 – O Que é um Flow?

Um Flow no Kotlin é uma ferramenta para lidar com fluxos de dados assíncronos. Ele funciona como um pipeline que emite valores ao longo do tempo, permitindo que você lide com streams de dados de forma eficiente.

Características principais:

  1. Assíncrono: O Flow emite valores de forma não bloqueante.
  2. Cold Stream: Um Flow só começa a emitir valores quando há um "coletor" (ou seja, quando alguém consome os dados).
  3. Cancelável: Se o coletor for cancelado, o fluxo também é cancelado automaticamente.

3 – Criando um Flow

Exemplo Simples de um Flow

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

fun main() = runBlocking {
    val fluxo = flow {
        for (i in 1..3) {
            emit(i) // Emite um valor
            delay(1000) // Simula um intervalo entre emissões
        }
    }

    fluxo.collect { valor ->
        println("Recebido: $valor")
    }
}
Enter fullscreen mode Exit fullscreen mode

Saída no console

Recebido: 1
Recebido: 2
Recebido: 3

Explicação:

  • emit: Envia valores para o fluxo.
  • collect: Consome os valores emitidos pelo fluxo.

4 – Comparação: Flow vs. Outras Abordagens

Aspecto Flow suspend async
Fluxo de dados contínuo Sim Não Não
Multiplos valores Sim Não (apenas um valor por chamada) Não (retorna um único valor).
Cancelável Sim Sim Sim
Exemplo típico Streams de eventos Chamadas assíncronas simples Cálculos paralelos.

5 – Transformando Dados com Flow

O verdadeiro poder do Flow está em sua capacidade de transformar os dados emitidos com operadores.

Exemplo: Usando operadores como map e filter

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

fun main() = runBlocking {
    val fluxo = flow {
        for (i in 1..5) {
            emit(i)
        }
    }

    fluxo
        .filter { it % 2 == 0 } // Filtra valores pares
        .map { it * 10 } // Multiplica os valores por 10
        .collect { valor ->
            println("Transformado: $valor")
        }
}
Enter fullscreen mode Exit fullscreen mode

Saída no console

Transformado: 20
Transformado: 40

6 – Testando Fluxos com Turbine

O Turbine é uma biblioteca que facilita a validação de valores emitidos por um Flow.

Exemplo com Turbine

import app.cash.turbine.test
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.test.*

fun main() = runTest {
    // Cria um fluxo que emite dois valores com um atraso entre eles
    val fluxo = flow {
        println("Emitindo valor 1")
        emit(1) // Emite o primeiro valor
        delay(500) // Aguarda 500ms
        println("Emitindo valor 2")
        emit(2) // Emite o segundo valor
    }

    // Testa o fluxo
    fluxo.test {
        val primeiroValor = awaitItem() // Aguarda o primeiro valor
        println("Valor recebido do fluxo: $primeiroValor")
        assert(primeiroValor == 1) // Valida o primeiro valor

        val segundoValor = awaitItem() // Aguarda o segundo valor
        println("Valor recebido do fluxo: $segundoValor")
        assert(segundoValor == 2) // Valida o segundo valor

        awaitComplete() // Verifica se o fluxo foi concluído
        println("Fluxo concluido com sucesso!")
    }
}
Enter fullscreen mode Exit fullscreen mode

Saída esperada no terminal

Emitindo valor 1
Valor recebido do fluxo: 1
Emitindo valor 2
Valor recebido do fluxo: 2
Fluxo concluido com sucesso!

7 – Casos Reais de Uso do Flow

7.1 – Atualização em Tempo Real

Em um aplicativo de bate-papo, você pode usar um Flow para transmitir mensagens novas à interface do usuário conforme elas chegam do servidor.

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

fun main() = runBlocking {
    val mensagens = flow {
        val novasMensagens = listOf("Oi", "Como você está?", "Até logo!")
        for (mensagem in novasMensagens) {
            emit(mensagem)
            delay(1000) // Simula intervalo entre mensagens
        }
    }

    mensagens.collect { mensagem ->
        println("Nova mensagem: $mensagem")
    }
}
Enter fullscreen mode Exit fullscreen mode

7.2 – Processamento de Dados em Lotes

Imagine um sistema que precisa processar lotes de dados grandes em intervalos regulares. O Flow facilita essa implementação.

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

fun main() = runBlocking {
    val fluxoDeLotes = flow {
        val lotes = listOf("Lote1", "Lote2", "Lote3")
        for (lote in lotes) {
            emit(lote)
            delay(2000) // Simula tempo de processamento
        }
    }

    fluxoDeLotes.collect { lote ->
        println("Processando: $lote")
    }
}
Enter fullscreen mode Exit fullscreen mode

8 – Conclusão

O Flow é uma ferramenta poderosa para lidar com dados assíncronos no Kotlin, permitindo a emissão, transformação e consumo de valores em tempo real. Ele é essencial para construir aplicações modernas, especialmente em cenários que exigem a manipulação de streams contínuos de eventos.

Resumo:

  1. O Flow é ideal para fluxos de dados contínuos e canceláveis.
  2. Operadores como map e filter facilitam a transformação dos dados emitidos.
  3. Ferramentas como o Turbine simplificam os testes de fluxos.

Referências:
Documentação oficial do Kotlin sobre corrotinas
Documentação do Turbine

Quadratic AI

Quadratic AI – The Spreadsheet with AI, Code, and Connections

  • AI-Powered Insights: Ask questions in plain English and get instant visualizations
  • Multi-Language Support: Seamlessly switch between Python, SQL, and JavaScript in one workspace
  • Zero Setup Required: Connect to databases or drag-and-drop files straight from your browser
  • Live Collaboration: Work together in real-time, no matter where your team is located
  • Beyond Formulas: Tackle complex analysis that traditional spreadsheets can't handle

Get started for free.

Watch The Demo 📊✨

Top comments (0)

Image of PulumiUP 2025

From Cloud to Platforms: What Top Engineers Are Doing Differently

Hear insights from industry leaders about the current state and future of cloud and IaC, platform engineering, and security.

Save Your Spot

👋 Kindness is contagious

Explore a trove of insights in this engaging article, celebrated within our welcoming DEV Community. Developers from every background are invited to join and enhance our shared wisdom.

A genuine "thank you" can truly uplift someone’s day. Feel free to express your gratitude in the comments below!

On DEV, our collective exchange of knowledge lightens the road ahead and strengthens our community bonds. Found something valuable here? A small thank you to the author can make a big difference.

Okay