launch — un Coroutine Builder en Kotlin que inicia una corrutina sin devolver un resultado, retornando un objeto Job para controlar la ejecución. Este builder implementa el patrón fire-and-forget: la corrutina comienza a trabajar en un hilo de fondo y finaliza automáticamente. Según la documentación de JetBrains, 2024, launch es la forma principal de ejecutar tareas paralelas en Kotlin Coroutines.
Puntos clave
launch es una función de extensión de Kotlin, disponible mediante la importación de kotlinx.coroutines, que crea una nueva corrutina en un CoroutineScope dado. A diferencia de las funciones normales, el código dentro de launch se ejecuta concurrentemente — la corrutina puede suspenderse sin bloquear un hilo y reanudarse más tarde.
El builder launch es un bloque fundamental del modelo de corrutinas de Kotlin. No devuelve un valor calculado pero retorna un objeto Job que permite controlar la ejecución de la corrutina. Todas las corrutinas hijas lanzadas mediante launch dentro de otra corrutina están vinculadas a la padre.
El builder launch se define como una función inline con varios parámetros: CoroutineScope, CoroutineContext, CoroutineStart y un bloque suspend. Los parámetros tienen valores por defecto, lo que hace que launch sea conveniente para escenarios típicos.
public fun CoroutineScope.launch(
context: CoroutineContext = EmptyCoroutineContext,
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> Unit
): Job
El parámetro context acepta un CoroutineContext que combina un dispatcher, un manejador de excepciones y un elemento con nombre. Lo más frecuente es pasar Dispatchers.IO, Dispatchers.Main o SupervisorJob para aislar errores.
Job — el objeto devuelto que representa el ciclo de vida de la corrutina. Un Job puede estar en estados: New, Active, Completing, Completed, Cancelling, Cancelled. Cada estado refleja el estado de ejecución y permite reaccionar a los cambios.
val job = CoroutineScope(Dispatchers.IO).launch {
repeat(10) { i ->
delay(1000L)
println("Progreso: $i")
}
}
println("El trabajo está activo: ${job.isActive}")
delay(2500L)
job.cancel()
println("El trabajo está cancelado: ${job.isCancelled}")
Job soporta una jerarquía: si una corrutina padre es cancelada, todas las hijas se cancelan automáticamente. SupervisorJob cambia este comportamiento — las corrutinas hijas no se cancelan cuando una de ellas falla.
La concurrencia estructurada significa que cada corrutina se lanza dentro de un CoroutineScope específico, y el scope no se completa hasta que todas las corrutinas hijas terminan su trabajo. launch soporta completamente este principio — las corrutinas lanzadas dentro de otra corrutina son sus hijas.
Con llamadas launch anidadas, se forma un árbol de corrutinas. La corrutina padre espera a que todas las hijas se completen, garantizando un orden de ejecución predecible y simplificando la gestión de recursos.
fun main() = runBlocking {
launch {
launch {
delay(1000L)
println("Hijo 1 completado")
}
launch {
delay(500L)
println("Hijo 2 completado")
}
println("Todos los hijos completan antes de esta línea")
}
}
Este comportamiento difiere de la concurrencia basada en hilos, donde los hilos hijos no están vinculados al padre. En las corrutinas, el padre no se completa hasta que todos los hijos terminan su trabajo.
El manejo de excepciones en launch depende del tipo de Job. Para un Job normal, las excepciones se propagan a la corrutina padre y la cancelan. Para SupervisorJob o SupervisorScope, las excepciones se aíslan — un error en una corrutina hija no afecta a las demás.
val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
scope.launch {
try {
riskyOperation()
} catch (e: Exception) {
println("Capturado: ${e.message}")
}
}
scope.launch {
println("Esto aún funciona gracias a SupervisorJob")
}
Para el manejo global de excepciones no capturadas, se usa CoroutineExceptionHandler. Captura las excepciones que no fueron manejadas dentro de la corrutina y permite registrar el error sin bloquear la aplicación.
En Android, launch se usa en todas partes: desde ViewModel hasta WorkManager. El patrón principal es usar lifecycleScope en Fragment y viewModelScope en ViewModel para la cancelación automática de corrutinas al finalizar el ciclo de vida del 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) }
}
}
}
}
viewModelScope cancela automáticamente las corrutinas cuando la ViewModel se destruye. Esto elimina fugas y asegura que las operaciones en segundo plano no continúen después de perder el contexto. Adicionalmente, se puede usar withContext para cambiar entre dispatchers.
Preguntas frecuentes
launch devuelve un Job y no retorna un resultado, mientras que async devuelve Deferred<T> para obtener el resultado. launch se usa para operaciones fire-and-forget, async — cuando necesitas esperar y usar el valor devuelto.
Llama a job.cancel() en el objeto Job guardado. Para cancelación grupal, cancela todo el CoroutineScope mediante scope.cancel(). La corrutina debe ser cooperativa — verificar isActive o usar funciones suspend cancelables.
Usa try-catch dentro del bloque launch o pasa CoroutineExceptionHandler en el CoroutineContext. Para aislar errores, usa SupervisorJob — entonces una excepción en una corrutina hija no cancelará las demás.
No, launch es una función de extensión de CoroutineScope. Sin un scope, la corrutina no puede seguir el principio de concurrencia estructurada. Usa GlobalScope.launch con precaución — crea una corrutina sin vinculación al ciclo de vida.
El número está limitado por el pool de hilos del dispatcher. Dispatchers.Default usa tantos hilos como núcleos de CPU. Dispatchers.IO soporta hasta 64 hilos. Si se lanzan más corrutinas, se ponen en cola.
Resumen
Desarrollaremos una aplicación móvil llave en mano
IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.
Lea también