launch — um Coroutine Builder em Kotlin que inicia uma corrotina sem retornar um resultado, devolvendo um objeto Job para controlar a execução. Este builder implementa o padrão fire-and-forget: a corrotina começa a trabalhar em uma thread de fundo e termina automaticamente. De acordo com a documentação da JetBrains, 2024, o launch é a principal forma de executar tarefas paralelas em Kotlin Coroutines.
Pontos principais
launch é uma função de extensão do Kotlin, disponível através da importação kotlinx.coroutines, que cria uma nova corrotina em um CoroutineScope específico. Ao contrário das funções normais, o código dentro do launch executa concorrentemente — a corrotina pode suspender sem bloquear uma thread e retomar mais tarde.
O builder launch é um bloco fundamental do modelo de corrotinas do Kotlin. Ele não retorna um valor calculado, mas retorna um objeto Job que permite controlar a execução da corrotina. Todas as corrotinas filhas iniciadas via launch dentro de outra corrotina estão vinculadas à corrotina pai.
O builder launch é definido como uma função inline com vários parâmetros: CoroutineScope, CoroutineContext, CoroutineStart e um bloco suspend. Os parâmetros têm valores padrão, tornando o launch conveniente para cenários típicos.
public fun CoroutineScope.launch(
context: CoroutineContext = EmptyCoroutineContext,
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> Unit
): Job
O parâmetro context aceita um CoroutineContext que combina um dispatcher, um manipulador de exceções e um elemento nomeado. Na maioria das vezes, Dispatchers.IO, Dispatchers.Main ou SupervisorJob são passados para isolar erros.
Job — o objeto retornado que representa o ciclo de vida da corrotina. Um Job pode estar nos estados: New, Active, Completing, Completed, Cancelling, Cancelled. Cada estado reflete o status de execução e permite reagir a mudanças.
val job = CoroutineScope(Dispatchers.IO).launch {
repeat(10) { i ->
delay(1000L)
println("Progresso: $i")
}
}
println("Job está ativo: ${job.isActive}")
delay(2500L)
job.cancel()
println("Job está cancelado: ${job.isCancelled}")
O Job suporta uma hierarquia: se uma corrotina pai for cancelada, todas as filhas são automaticamente canceladas. SupervisorJob altera esse comportamento — as corrotinas filhas não são canceladas quando uma delas falha.
Concorrência estruturada significa que cada corrotina é iniciada dentro de um CoroutineScope específico, e o escopo não será concluído até que todas as corrotinas filhas terminem seu trabalho. launch suporta totalmente este princípio — corrotinas iniciadas dentro de outra corrotina são suas filhas.
Com chamadas launch aninhadas, forma-se uma árvore de corrotinas. A corrotina pai aguarda a conclusão de todas as filhas, garantindo uma ordem de execução previsível e simplificando o gerenciamento de recursos.
fun main() = runBlocking {
launch {
launch {
delay(1000L)
println("Filho 1 concluído")
}
launch {
delay(500L)
println("Filho 2 concluído")
}
println("Todos os filhos concluem antes desta linha")
}
}
Este comportamento difere da concorrência baseada em threads, onde as threads filhas não estão vinculadas à thread pai. Em corrotinas, o pai não é concluído até que todas as filhas terminem seu trabalho.
O tratamento de exceções no launch depende do tipo de Job. Para um Job normal, as exceções se propagam para a corrotina pai e a cancelam. Para SupervisorJob ou SupervisorScope, as exceções são isoladas — um erro em uma corrotina filha não afeta as outras.
val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
scope.launch {
try {
riskyOperation()
} catch (e: Exception) {
println("Capturado: ${e.message}")
}
}
scope.launch {
println("Isso ainda funciona graças ao SupervisorJob")
}
Para o tratamento global de exceções não capturadas, usa-se CoroutineExceptionHandler. Ele captura exceções que não foram tratadas dentro da corrotina e permite registrar o erro sem travar a aplicação.
No Android, o launch é usado em toda parte: desde ViewModel até WorkManager. O padrão principal é usar lifecycleScope no Fragment e viewModelScope na ViewModel para cancelamento automático de corrotinas ao final do ciclo de vida do componente.
class ProfileViewModel : ViewModel() {
private val repository = UserRepository()
fun loadProfile(userId: String) {
viewModelScope.launch(Dispatchers.IO) {
val profile = repository.fetchProfile(userId)
withContext(Dispatchers.Main) {
_profileState.update { it.copy(profile = profile) }
}
}
}
}
O viewModelScope cancela automaticamente as corrotinas quando a ViewModel é destruída. Isso elimina vazamentos e garante que operações em segundo plano não continuem após a perda de contexto. Adicionalmente, withContext pode ser usado para alternar entre dispatchers.
Perguntas frequentes
launch retorna um Job e não retorna um resultado, enquanto async retorna Deferred<T> para obter o resultado. launch é usado para operações fire-and-forget, async — quando você precisa esperar e usar o valor retornado.
Chame job.cancel() no objeto Job salvo. Para cancelamento em grupo, cancele todo o CoroutineScope via scope.cancel(). A corrotina deve ser cooperativa — verifique isActive ou use funções suspend canceláveis.
Use try-catch dentro do bloco launch ou passe CoroutineExceptionHandler no CoroutineContext. Para isolar erros, use SupervisorJob — então uma exceção em uma corrotina filha não cancelará as outras.
Não, launch é uma função de extensão de CoroutineScope. Sem um escopo, a corrotina não pode seguir o princípio de concorrência estruturada. Use GlobalScope.launch com cautela — cria uma corrotina sem vínculo com o ciclo de vida.
O número é limitado pelo pool de threads do dispatcher. Dispatchers.Default usa tantas threads quanto o número de núcleos de CPU. Dispatchers.IO suporta até 64 threads. Se mais corrotinas forem lançadas, elas são enfileiradas.
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