launch — essenza, avvio fire-and-forget delle coroutine e come funziona

Autore: IT Sectr Pubblicato: 2026-06-22 Tempo di lettura: 7 min

launch — un Coroutine Builder in Kotlin che avvia una coroutine senza restituire un risultato, restituendo un oggetto Job per controllare l'esecuzione. Questo builder implementa il pattern fire-and-forget: la coroutine inizia a lavorare in un thread in background e termina automaticamente. Secondo la documentazione JetBrains, 2024, launch è il modo principale per eseguire attività parallele in Kotlin Coroutines.

Punti chiave

  • launch — un builder per avviare coroutine senza restituire risultato (fire-and-forget)
  • Job — un oggetto di controllo della coroutine con metodi cancel(), join(), isActive
  • launch si integra con CoroutineScope per la cancellazione automatica delle coroutine figlie
  • CoroutineStart.LAZY consente di posticipare l'esecuzione fino a una chiamata esplicita a start() o join()
  • launch in Android viene utilizzato per salvare nel database, chiamate di rete e aggiornamenti UI

Cos'è launch in Kotlin Coroutines?

launch è una funzione di estensione di Kotlin, disponibile tramite l'import kotlinx.coroutines, che crea una nuova coroutine in un determinato CoroutineScope. A differenza delle funzioni normali, il codice all'interno di launch viene eseguito concurrentemente — la coroutine può sospendersi senza bloccare un thread e riprendere più tardi.

Il builder launch è un blocco fondamentale del modello di coroutine di Kotlin. Non restituisce un valore calcolato ma restituisce un oggetto Job che consente di controllare l'esecuzione della coroutine. Tutte le coroutine figlie avviate tramite launch all'interno di un'altra coroutine sono legate alla coroutine padre.

Sintassi e parametri di launch

Il builder launch è definito come una funzione inline con diversi parametri: CoroutineScope, CoroutineContext, CoroutineStart e un blocco suspend. I parametri hanno valori predefiniti, rendendo launch comodo per scenari tipici.

kotlin
public fun CoroutineScope.launch(
    context: CoroutineContext = EmptyCoroutineContext,
    start: CoroutineStart = CoroutineStart.DEFAULT,
    block: suspend CoroutineScope.() -> Unit
): Job

Il parametro context accetta un CoroutineContext che combina un dispatcher, un gestore di eccezioni e un elemento nominato. Il più delle volte vengono passati Dispatchers.IO, Dispatchers.Main o SupervisorJob per isolare gli errori.

Job e gestione del ciclo di vita

Job — l'oggetto restituito che rappresenta il ciclo di vita della coroutine. Un Job può trovarsi negli stati: New, Active, Completing, Completed, Cancelling, Cancelled. Ogni stato riflette lo stato di esecuzione e consente di reagire ai cambiamenti.

kotlin
val job = CoroutineScope(Dispatchers.IO).launch {
    repeat(10) { i ->
        delay(1000L)
        println("Avanzamento: $i")
    }
}

println("Job è attivo: ${job.isActive}")
delay(2500L)
job.cancel()
println("Job è cancellato: ${job.isCancelled}")

Job supporta una gerarchia: se una coroutine padre viene cancellata, tutte le coroutine figlie vengono automaticamente cancellate. SupervisorJob modifica questo comportamento — le coroutine figlie non vengono cancellate quando una di esse fallisce.

Concorrenza strutturata in launch

La concorrenza strutturata significa che ogni coroutine viene avviata all'interno di un CoroutineScope specifico e lo scope non viene completato fino a quando tutte le coroutine figlie non terminano il loro lavoro. launch supporta pienamente questo principio — le coroutine avviate all'interno di un'altra coroutine sono sue figlie.

Chiamate launch annidate

Con chiamate launch annidate, si forma un albero di coroutine. La coroutine padre attende il completamento di tutte le figlie, garantendo un ordine di esecuzione prevedibile e semplificando la gestione delle risorse.

kotlin
fun main() = runBlocking {
    launch {
        launch {
            delay(1000L)
            println("Figlio 1 completato")
        }
        launch {
            delay(500L)
            println("Figlio 2 completato")
        }
        println("Tutti i figli completano prima di questa riga")
    }
}

Questo comportamento differisce dalla concorrenza basata su thread, dove i thread figli non sono legati al thread padre. Nelle coroutine, il padre non viene completato fino a quando tutte le figlie non terminano il loro lavoro.

Gestione delle eccezioni in launch

La gestione delle eccezioni in launch dipende dal tipo di Job. Per un Job normale, le eccezioni si propagano alla coroutine padre e la cancellano. Per SupervisorJob o SupervisorScope, le eccezioni sono isolate — un errore in una coroutine figlia non influisce sulle altre.

kotlin
val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
scope.launch {
    try {
        riskyOperation()
    } catch (e: Exception) {
        println("Catturato: ${e.message}")
    }
}
scope.launch {
    println("Questo funziona ancora grazie a SupervisorJob")
}

Per la gestione globale delle eccezioni non catturate, viene utilizzato CoroutineExceptionHandler. Cattura le eccezioni che non sono state gestite all'interno della coroutine e consente di registrare l'errore senza bloccare l'applicazione.

Esempi di utilizzo di launch in Android

In Android, launch viene utilizzato ovunque: da ViewModel a WorkManager. Il pattern principale è l'uso di lifecycleScope in Fragment e viewModelScope in ViewModel per la cancellazione automatica delle coroutine al termine del ciclo di vita del componente.

kotlin
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 cancella automaticamente le coroutine quando il ViewModel viene distrutto. Questo elimina le perdite di memoria e garantisce che le operazioni in background non continuino dopo la perdita del contesto. Inoltre, withContext può essere utilizzato per passare da un dispatcher all'altro.

Domande frequenti

Qual è la differenza tra launch e async in Kotlin Coroutines?

launch restituisce un Job e non restituisce un risultato, mentre async restituisce Deferred<T> per ottenere il risultato. launch viene utilizzato per operazioni fire-and-forget, async — quando è necessario attendere e utilizzare il valore restituito.

Come cancellare una coroutine avviata tramite launch?

Chiama job.cancel() sull'oggetto Job salvato. Per la cancellazione di gruppo, cancella l'intero CoroutineScope tramite scope.cancel(). La coroutine deve essere cooperativa — verificare isActive o utilizzare funzioni suspend cancellabili.

Cosa fare se launch lancia un'eccezione?

Usa try-catch all'interno del blocco launch o passa CoroutineExceptionHandler in CoroutineContext. Per isolare gli errori, usa SupervisorJob — allora un'eccezione in una coroutine figlia non cancellerà le altre.

Si può usare launch senza CoroutineScope?

No, launch è una funzione di estensione di CoroutineScope. Senza uno scope, la coroutine non può seguire il principio della concorrenza strutturata. Usa GlobalScope.launch con cautela — crea una coroutine senza legame con il ciclo di vita.

Quante coroutine launch possono essere eseguite simultaneamente?

Il numero è limitato dal pool di thread del dispatcher. Dispatchers.Default utilizza un numero di thread pari al numero di core CPU. Dispatchers.IO supporta fino a 64 thread. Se vengono avviate più coroutine, vengono messe in coda.

Riepilogo

  • launch — il builder principale per coroutine fire-and-forget, restituisce un oggetto Job
  • Job fornisce metodi di controllo: cancel(), join(), isActive, isCancelled, isCompleted
  • Concorrenza strutturata garantisce la cancellazione delle coroutine figlie quando il padre viene cancellato
  • Gestione delle eccezioni dipende dal tipo di Job: normale propaga gli errori, SupervisorJob li isola
  • lifecycleScope e viewModelScope — soluzioni pronte per avviare coroutine in Android
  • CoroutineStart.LAZY posticipa l'esecuzione fino a una chiamata esplicita a start() o join()
  • launch in Android viene utilizzato per richieste di rete, scrittura nel database, analisi e caching

Svilupperemo un'applicazione mobile chiavi in mano

IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.

Discuti il progetto

Leggi anche