Pular para o conteúdo

Boas práticas e padrões · Concorrência · 6 min de leitura

Corrotinas e Flow em Kotlin

Corrotinas escrevem código assíncrono como se fosse sequencial; Flow entrega vários valores ao longo do tempo. Escopo e dispatcher certos evitam vazamentos e travamentos.

viewModelScopeTela → launch { }1launch { } → withContext(IO)2withContext(IO) → Room / API3withContext(IO) → StateFlow4StateFlow → Tela5Tela — coleta o estadoTelacoleta o estadolaunch { } — Mainlaunch { }MainwithContext(IO) — rede / bancowithContext(IO)rede / bancoStateFlow — estado da telaStateFlowestado da telaRoom / APIRoom / API

Arraste para o lado para ver o diagrama inteiro.

Quando a tela fecha, o viewModelScope cancela tudo o que lançou: nada continua rodando à toa.

Corrotinas

Uma função suspend pode pausar sem bloquear a thread (esperando a rede, por exemplo) e continuar depois. Toda corrotina vive num escopo (viewModelScope, lifecycleScope, coroutineScope): cancelar o escopo cancela os filhos — é a concorrência estruturada.

  • Dispatchers.Main: UI.
  • Dispatchers.IO: rede, disco, banco.
  • Dispatchers.Default: cálculo pesado.

Nunca use GlobalScope nem runBlocking em código de app.

Flow

Flow é uma sequência assíncrona e fria (só roda quando alguém coleta). StateFlow guarda o último valor (estado da tela); SharedFlow serve para eventos. Na tela, colete com collectAsStateWithLifecycle() (Compose) ou repeatOnLifecycle(STARTED) para parar quando o app vai para o fundo.

Erros e cancelamento

Exceções sobem pelo escopo; trate com try/catch dentro da corrotina ou catch { } no Flow. Não engula CancellationException: ela é o mecanismo de cancelamento. Em laços longos, chame ensureActive() ou funções suspensas para o cancelamento funcionar.

No código: antes e depois

✗ AntesKotlin
class PerfilViewModel(private val api: Api) : ViewModel() {
    var perfil: Perfil? = null
    fun carregar() {
        GlobalScope.launch { // não é cancelado quando a tela fecha
            perfil = api.perfil() // estado mutável lido por outra thread
        }
    }
}
✓ DepoisKotlin
class PerfilViewModel(private val repo: PerfilRepository) : ViewModel() {
    private val _ui = MutableStateFlow<PerfilUi>(PerfilUi.Carregando)
    val ui: StateFlow<PerfilUi> = _ui.asStateFlow()

    fun carregar() = viewModelScope.launch {
        _ui.value = try {
            PerfilUi.Pronto(repo.perfil()) // o repositório usa withContext(Dispatchers.IO)
        } catch (e: IOException) {
            PerfilUi.Erro("Sem conexão")
        }
    }
}

// Na tela (Compose):
// val ui by viewModel.ui.collectAsStateWithLifecycle()

Escopo do ViewModel, estado exposto como StateFlow imutável e só a exceção esperada tratada (o cancelamento continua passando).

Em resumo

Perguntar à IA

Monte um prompt pronto sobre Corrotinas e Flow em Kotlin na sua linguagem e no seu caso, e abra num chat gratuito.

ChatGPT Claude Perplexity

O prompt vai para o site que você escolher. Não cole senhas, tokens nem dados reais de clientes. Para Gemini e outros, copie e cole.

Referências

Continue aprendendo

Todos os temas de boas práticas e padrões →