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.
Arraste para o lado para ver o diagrama inteiro.
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
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
}
}
} 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
- suspend pausa sem bloquear a thread.
- Sempre num escopo com ciclo de vida.
- IO para rede e disco; Main para UI.
- StateFlow para estado, coletado com lifecycle.
Perguntar à IA
Monte um prompt pronto sobre Corrotinas e Flow em Kotlin na sua linguagem e no seu caso, e abra num chat gratuito.
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.