Coroutine Builder — funções do Kotlin Coroutines que criam e iniciam corrotinas, definindo como elas são executadas. Os construtores launch, async, runBlocking e produce cobrem diferentes cenários: de tarefas em segundo plano a computações paralelas com retorno de resultado. De acordo com a JetBrains, 2024, o Coroutine Builder é a base do modelo de corrotinas, fornecendo concorrência estruturada e gerenciamento do ciclo de vida.
Principais pontos
Coroutine Builder é uma função de extensão do Kotlin que recebe um CoroutineScope e um bloco suspend, criando e iniciando uma nova corrotina. Cada construtor define como a corrotina será executada: com ou sem retorno de resultado, com bloqueio de thread ou assincronamente. Os construtores são os pontos de entrada no modelo de corrotinas da linguagem.
Todos os construtores trabalham através do CoroutineScope, que gerencia o ciclo de vida das corrotinas filhas. Quando um escopo é cancelado, todas as corrotinas iniciadas através dele são automaticamente canceladas — este é o princípio da concorrência estruturada. Esta abordagem previne vazamentos de corrotinas e garante um término previsível.
import kotlinx.coroutines.*
fun main() = runBlocking {
// Os construtores executam dentro de CoroutineScope
val job = launch {
delay(1000L)
println("Mundo!")
}
println("Olá,")
job.join()
}
Kotlin fornece quatro construtores de corrotinas incorporados: launch, async, runBlocking e produce. Cada um tem seu próprio tipo de retorno e área de aplicação. Para desenvolvimento móvel Android, os principais são launch e async — eles funcionam de maneira não bloqueante e se integram com componentes arquiteturais.
| Construtor | Tipo de retorno | Bloqueio de thread | Cenário |
|---|---|---|---|
| launch | Job | Não | Tarefas fire-and-forget |
| async | Deferred<T> | Não | Computações paralelas |
| runBlocking | T | Sim | Testes, função main |
| produce | ReceiveChannel<E> | Não | Transmissão (obsoleto) |
Cada construtor aceita parâmetros adicionais: CoroutineStart (estratégia de início), CoroutineContext (despachante, exceções) e um bloco de código nomeado. Por padrão, a corrotina inicia imediatamente (CoroutineStart.DEFAULT).
launch é o construtor mais usado no desenvolvimento Android. Ele inicia uma corrotina que não retorna um resultado e retorna um objeto Job para gerenciar seu ciclo de vida. É a escolha ideal para operações que precisam apenas de um efeito colateral: salvar no banco de dados, enviar análises, atualizar a UI.
O construtor launch aceita CoroutineScope, um CoroutineContext opcional e um bloco suspend. O Job retornado permite cancelar a corrotina, aguardar sua conclusão ou verificar seu status.
val scope = CoroutineScope(Dispatchers.IO + SupervisorJob())
val job: Job = scope.launch(CoroutineStart.LAZY) {
val data = fetchFromNetwork()
saveToDatabase(data)
}
job.start()
job.join()
O parâmetro CoroutineStart.LAZY adia a execução até uma chamada explícita a start() ou join(). Isso é útil para inicialização tardia e execução condicional. Para execução imediata padrão, usa-se CoroutineStart.DEFAULT ou o parâmetro é omitido.
async é um construtor que retorna Deferred<T> — uma promessa assíncrona de um resultado. Chamar await() suspende a corrotina até obter o resultado, sem bloquear a thread. Este é o mecanismo principal para tarefas paralelas em corrotinas Kotlin.
async é especialmente eficaz quando você precisa executar múltiplas operações independentes simultaneamente. Ao contrário de chamadas sequenciais a funções suspend, async inicia corrotinas em paralelo, reduzindo o tempo total de execução.
suspend fun fetchUserData(): UserData {
val deferred1 = CoroutineScope(Dispatchers.IO).async { api.getProfile() }
val deferred2 = CoroutineScope(Dispatchers.IO).async { api.getSettings() }
val deferred3 = CoroutineScope(Dispatchers.IO).async { api.getNotifications() }
return UserData(
profile = deferred1.await(),
settings = deferred2.await(),
notifications = deferred3.await()
)
}
Deferred herda de Job, então async suporta todas as operações do ciclo de vida: cancelamento, espera por conclusão, tratamento de exceções. Quando um escopo é cancelado, as corrotinas Deferred filhas são canceladas automaticamente.
runBlocking é o único construtor que bloqueia a thread atual até a corrotina ser concluída. Ele cria um novo CoroutineScope e inicia a corrotina passada, bloqueando a thread chamadora. É usado em pontos de entrada main(), em testes e ao integrar com código bloqueante.
runBlocking é justificado em três cenários: o ponto de entrada da aplicação (main), testes unitários de funções suspend e integração com bibliotecas baseadas em callbacks onde suspend não pode ser usado. Em código Android de produção, usar runBlocking na thread principal não é recomendado.
class CoroutineTest {
@Test
fun `test suspend function`() = runBlocking {
val result = mySuspendFunction()
assertEquals("expected", result)
}
}
Para testes, recomenda-se usar kotlinx-coroutines-test com TestCoroutineDispatcher em vez de runBlocking — isso fornece controle de tempo e evita bloqueios no ambiente de teste.
A escolha do Coroutine Builder depende do resultado retornado e do cenário de execução. Se a operação não requer retorno de dados — use launch. Se você precisa do resultado de uma operação assíncrona — use async. runBlocking deve ser usado apenas para ponte, e substitua produce por Flow para fluxos reativos.
Em projetos Android que usam Kotlin Coroutines, o par principal de construtores são launch e async. launch é usado em ViewModel e UseCases para iniciar corrotinas, enquanto async é usado para requisições paralelas à rede ou banco de dados. Bibliotecas modernas (Ktor, Room) já suportam funções suspend, o que minimiza a necessidade de uso direto de async.
Perguntas frequentes
launch retorna Job e não retorna um resultado de execução, enquanto async retorna Deferred<T> — um objeto do qual o resultado pode ser obtido via await(). launch é usado para operações fire-and-forget, async para tarefas que retornam dados.
Não é recomendado. runBlocking na thread principal causa ANR e bloqueia a UI. Use lifecycleScope.launch dentro de Activity e Fragment — é uma solução incorporada sem bloqueios.
O construtor launch retorna um objeto Job, que permite controlar o ciclo de vida da corrotina: cancelar (cancel), aguardar conclusão (join), verificar status (isActive, isCompleted, isCancelled).
Deferred<T> é uma promessa assíncrona de um resultado, retornada pelo construtor async. Ele herda de Job e adiciona métodos await() para obter o resultado, getCompleted() para acesso não bloqueante e getCompletionExceptionOrNull() para verificar exceções.
Use o parâmetro CoroutineStart.LAZY: scope.launch(start = CoroutineStart.LAZY) { ... }. Depois chame job.start() ou job.join() para a execução real. Isso é útil para inicialização tardia e execução condicional de corrotinas.
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