Coroutines (corrotinas) são threads leves do Kotlin para programação assíncrona, disponíveis através da biblioteca kotlinx.coroutines. De acordo com JetBrains Kotlin Documentation, 2026, Coroutines permitem suspender a execução de uma função sem bloquear uma thread, ao contrário das Threads tradicionais. As corrotinas são executadas em um pool limitado de threads, tornando-as mil vezes mais leves que threads nativas. Kotlin Coroutines são totalmente integradas com Android Jetpack, Retrofit, Room e outras bibliotecas populares do ecossistema Android.
Pontos Principais
Coroutines são um mecanismo de programação assíncrona em Kotlin, implementado na biblioteca kotlinx.coroutines. Ao contrário das threads do sistema operacional, as corrotinas não estão vinculadas a uma thread específica: podem suspender em uma thread e retomar em outra. Uma única thread pode executar milhares de corrotinas, alternando entre elas com sobrecarga mínima.
As corrotinas apareceram no Kotlin 1.3 (2018) como um recurso experimental e tornaram-se estáveis no Kotlin 1.5 (2021). Coroutines resolvem o problema de callback hell de forma semelhante ao async/await, mas fornecem uma API mais rica: canais (Channel), Flow, tratamento de exceções na hierarquia Job e integração direta com Android Lifecycle.
Segundo a JetBrains (2025), cada corrotina consome cerca de 100 bytes de memória contra 1+ MB de uma thread nativa. Isso permite executar milhões de corrotinas em uma única aplicação sem risco de OutOfMemoryError. É a leveza das corrotinas que as torna a ferramenta preferida para assincronia no Android.
Cada corrotina Kotlin é compilada em uma máquina de estados usando Continuation Passing Style (CPS). O compilador adiciona um parâmetro Continuation oculto a cada função suspend. O Continuation contém o ponto de retomada e todas as variáveis locais. Quando uma corrotina suspende, o runtime salva o Continuation e, quando retoma, restaura-o em qualquer thread disponível do pool do Dispatcher.
suspend é uma palavra-chave do Kotlin que marca uma função como suspensível. Tal função só pode ser chamada de outra função suspend ou de uma corrotina. Dentro de uma função suspend, você pode chamar outras funções suspend em qualquer ordem, e cada ponto de chamada é um ponto potencial de suspensão.
A mecânica é simples: quando uma função suspend chama outra função suspend, ela suspende nesse ponto, liberando a thread. Após a função chamada ser concluída, o runtime continua a execução a partir do local salvo. Isso é chamado de cooperative cancellation — nenhuma thread é bloqueada.
Importante: uma função suspend não é assíncrona por padrão. A ordem de execução permanece sequencial se launch ou async não forem usados. suspend apenas permite que a função seja pausada sem bloquear a thread e faça parte do contexto de corrotina. Continuation Passing Style é um modelo de compilação onde cada função suspend recebe um callback Continuation oculto, e o compilador gera uma máquina de estados para gerenciar suspensões e retomadas.
CoroutineScope é um contexto que define o ciclo de vida das corrotinas. Todas as corrotinas devem ser lançadas dentro de um escopo. Quando um escopo é cancelado (por exemplo, quando uma Activity termina), todas as suas corrotinas filhas são automaticamente canceladas. Isso evita vazamentos de tarefas em segundo plano. Android Jetpack fornece escopos prontos para cada componente: viewModelScope para ViewModel e lifecycleScope para Activity e Fragment, que são automaticamente cancelados quando o componente correspondente é destruído.
Concorrência Estruturada (Structured Concurrency) é um princípio que garante que uma corrotina não será concluída até que todas as suas corrotinas filhas tenham sido concluídas. A hierarquia Job forma uma árvore: uma corrotina raiz cria um parent job, os filhos criam child jobs. Cancelar um parent job propaga-se para todos os filhos. Structured Concurrency é uma diferença fundamental entre corrotinas e threads.
| Scope | Onde é usado | Cancelamento |
|---|---|---|
| GlobalScope | Apenas para tarefas daemon | Não é cancelado automaticamente |
| viewModelScope | Android ViewModel | Ao limpar o ViewModel |
| lifecycleScope | Android Activity/Fragment | Ao destruir o lifecycle |
| coroutineScope | Dentro de função suspend | Ao cancelar o job pai |
Um Job normal cancela todos os siblings quando uma corrotina filha falha. SupervisorJob é uma exceção: uma falha em uma corrotina filha não afeta as outras. Isso é importante quando várias tarefas independentes são executadas em paralelo e uma delas pode falhar sem precisar cancelar as outras.
Dispatchers determinam em quais threads as corrotinas são executadas. Dispatchers.Main — a thread principal da UI Android. Dispatchers.IO — um pool para operações de bloqueio (rede, disco). Dispatchers.Default — para tarefas intensivas em CPU. Dispatchers.Unconfined — inicia na thread atual mas não garante permanecer nela. Escolher o Dispatcher correto é crítico para o desempenho: uma tarefa IO no Default bloqueará o pool de computação, enquanto uma tarefa de CPU no IO criará threads desnecessárias.
withContext — uma função para alternar o Dispatcher dentro de uma corrotina. Por exemplo, uma função suspend que analisa JSON pode alternar para Dispatchers.Default para computação e retornar ao Dispatchers.Main para atualizar a UI. withContext é o construtor mais usado no desenvolvimento Android.
launch — inicia uma corrotina, retorna um Job, não retorna resultado (fire-and-forget). async — inicia uma corrotina, retorna um Deferred do qual o resultado pode ser obtido via await. runBlocking — bloqueia a thread atual para executar uma corrotina (apenas para testes e funções main). Escolha do construtor depende do cenário: launch é adequado para eventos e atualizações, async para tarefas com resultado, runBlocking apenas para testes ou pontos de entrada.
Vamos considerar três cenários práticos: uma corrotina básica com launch, uma chamada paralela com async e tratamento de erros com SupervisorJob.
viewModelScope.launch inicia uma corrotina no contexto do ViewModel. Quando o ViewModel é limpo, a corrotina é automaticamente cancelada.
class ProfileViewModel : ViewModel() {
fun loadUser() {
viewModelScope.launch(Dispatchers.IO) {
val user = api.fetchUser()
withContext(Dispatchers.Main) {
showUser(user)
}
}
}
}
coroutineScope com async inicia três requisições em paralelo. Os resultados são coletados via .await(). Se alguma requisição falhar, todas são canceladas.
suspend fun loadDashboard(): Dashboard = coroutineScope {
val user = async { api.fetchUser() }
val posts = async { api.fetchPosts() }
val stats = async { api.fetchStats() }
Dashboard(user.await(), posts.await(), stats.await())
}
SupervisorJob permite que cada corrotina termine independentemente. Um erro em uma requisição não cancela as outras.
val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
scope.launch {
try { api.fetchUsers() } catch (e: Exception) { log(e) }
}
scope.launch {
try { api.fetchPosts() } catch (e: Exception) { log(e) }
}
Threads são um primitivo do sistema operacional. Cada thread tem sua própria pilha (~1 MB) e requer uma chamada de sistema para criação e alternância. Corrotinas são um primitivo da linguagem, não vinculado ao SO. Elas usam Continuation para salvar o estado e alternam no nível do runtime sem chamadas de sistema.
Segundo o Google (2025), usar corrotinas em vez de threads reduz o consumo de memória para tarefas em segundo plano em aplicativos Android em 90–95%. Todas as bibliotecas modernas do Android (Retrofit, Room, WorkManager) têm suporte integrado a corrotinas através de funções suspend. Ktor (framework cliente HTTP da JetBrains) também é construído inteiramente sobre corrotinas, fornecendo funções suspend para cada requisição sem API de callbacks. Room suporta corrotinas através de funções suspend no DAO, permitindo executar consultas ao banco de dados sem bloquear a thread principal.
As threads permanecem necessárias para código nativo via JNI, chamadas bloqueantes de CPU-intensive sem limite de tempo (renderização de vídeo, simulações) e ao integrar com bibliotecas C. Para todo o resto — corrotinas.
Perguntas Frequentes
Corrotina é uma unidade de trabalho suspensível executada em uma thread existente. Uma thread é um recurso do sistema com sua própria pilha. Corrotinas são milhares de vezes mais leves que threads e não bloqueiam recursos ao suspender.
Dispatchers.IO é projetado para operações de E/S bloqueantes (rede, arquivos) e pode criar novas threads quando necessário. Dispatchers.Default tem um pool de tamanho fixo (número de núcleos de CPU) para computações intensivas em CPU.
Job.cancel() cancela a corrotina e todos os seus filhos. Para verificar o cancelamento dentro de uma corrotina, use ensureActive() — ele lança uma CancellationException se a corrotina estiver cancelada.
Sim — através da biblioteca kotlinx-coroutines-rx3. Ela fornece funções awaitSingle, awaitFirst e outras para converter Observable/Single em funções suspend e vice-versa através de flowable.
Flow é um fluxo de dados assíncrono a frio, o equivalente em corrotinas do RxJava Observable. Flow emite valores sequencialmente e completa com uma exceção ou sucesso. Suporta map, filter, catch e outros operadores.
Resumo
Vamos desenvolver um aplicativo móvel chave na mão
A IT Sectr cria aplicativos para iOS e Android para startups e empresas desde 2017. Nós vamos aconselhá-lo e propor a melhor solução.
Leia também