Coroutine Builder: cos'è, tipi di costruttori di coroutine e come funzionano

Autore: IT Sectr Pubblicato: 2026-06-21 Tempo di lettura: 8 min

Coroutine Builder — funzioni di Kotlin Coroutines che creano e avviano coroutine, definendo come vengono eseguite. I costruttori launch, async, runBlocking e produce coprono diversi scenari: dalle attività in background ai calcoli paralleli con restituzione del risultato. Secondo JetBrains, 2024, Coroutine Builder è il fondamento del modello a coroutine, fornendo concorrenza strutturata e gestione del ciclo di vita.

Punti chiave

  • Coroutine Builder — una funzione che crea una coroutine all'interno di un CoroutineScope specifico
  • launch — avvia una coroutine senza restituire un risultato, restituisce un oggetto Job
  • async — avvia una coroutine restituendo Deferred, consentendo di ottenere il risultato tramite await()
  • runBlocking — blocca il thread corrente, usato come ponte tra codice bloccante e sospeso
  • produce — crea una coroutine con un canale per la trasmissione dei dati (deprecato a favore di Flow)

Cos'è un Coroutine Builder?

Coroutine Builder è una funzione di estensione di Kotlin che accetta un CoroutineScope e un blocco suspend, creando e avviando una nuova coroutine. Ogni costruttore definisce come la coroutine verrà eseguita: con o senza restituzione del risultato, con blocco del thread o in modo asincrono. I costruttori sono i punti di ingresso nel modello a coroutine del linguaggio.

Tutti i costruttori lavorano tramite CoroutineScope, che gestisce il ciclo di vita delle coroutine figlie. Quando un ambito viene annullato, tutte le coroutine avviate tramite esso vengono automaticamente annullate — questo è il principio della concorrenza strutturata. Questo approccio previene perdite di coroutine e garantisce un termine prevedibile.

kotlin
import kotlinx.coroutines.*

fun main() = runBlocking {
    // I costruttori vengono eseguiti all'interno di CoroutineScope
    val job = launch {
        delay(1000L)
        println("Mondo!")
    }
    println("Ciao,")
    job.join()
}

Principali tipi di costruttori di coroutine

Kotlin fornisce quattro costruttori di coroutine integrati: launch, async, runBlocking e produce. Ciascuno ha il proprio tipo di restituzione e area di applicazione. Per lo sviluppo mobile Android, i costruttori principali sono launch e async — funzionano in modo non bloccante e si integrano con i componenti architetturali.

CostruttoreTipo restituitoBlocco threadScenario
launchJobNoAttività fire-and-forget
asyncDeferred<T>NoCalcoli paralleli
runBlockingTTest, funzione main
produceReceiveChannel<E>NoStreaming (deprecato)

Ogni costruttore accetta parametri aggiuntivi: CoroutineStart (strategia di avvio), CoroutineContext (dispatcher, eccezioni) e un blocco di codice denominato. Per impostazione predefinita, la coroutine viene avviata immediatamente (CoroutineStart.DEFAULT).

launch: esecuzione fire-and-forget

launch è il costruttore più utilizzato nello sviluppo Android. Avvia una coroutine che non restituisce un risultato e restituisce un oggetto Job per gestirne il ciclo di vita. È la scelta ideale per operazioni che necessitano solo di un effetto collaterale: salvataggio nel database, invio di analisi, aggiornamento dell'interfaccia.

Sintassi e utilizzo di launch

Il costruttore launch accetta CoroutineScope, un CoroutineContext opzionale e un blocco suspend. Il Job restituito consente di annullare la coroutine, attendere il completamento o verificarne lo stato.

kotlin
val scope = CoroutineScope(Dispatchers.IO + SupervisorJob())
val job: Job = scope.launch(CoroutineStart.LAZY) {
    val data = fetchFromNetwork()
    saveToDatabase(data)
}
job.start()
job.join()

Il parametro CoroutineStart.LAZY posticipa l'esecuzione fino a una chiamata esplicita a start() o join(). Ciò è utile per l'inizializzazione ritardata e l'esecuzione condizionale. Per l'esecuzione immediata standard si usa CoroutineStart.DEFAULT o si omette il parametro.

async: calcoli paralleli con risultato

async è un costruttore che restituisce Deferred<T> — una promessa asincrona di un risultato. La chiamata a await() sospende la coroutine fino all'ottenimento del risultato, senza bloccare il thread. Questo è il meccanismo principale per le attività parallele nelle coroutine Kotlin.

Avvio di due richieste in parallelo

async è particolarmente efficace quando è necessario eseguire più operazioni indipendenti simultaneamente. A differenza delle chiamate sequenziali a funzioni suspend, async avvia le coroutine in parallelo, riducendo il tempo di esecuzione totale.

kotlin
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 eredita da Job, quindi async supporta tutte le operazioni del ciclo di vita: annullamento, attesa del completamento, gestione delle eccezioni. Quando un ambito viene annullato, le coroutine Deferred figlie vengono automaticamente annullate.

runBlocking: ponte verso il mondo bloccante

runBlocking è l'unico costruttore che blocca il thread corrente fino al completamento della coroutine. Crea un nuovo CoroutineScope e avvia la coroutine passata, bloccando il thread chiamante. Viene utilizzato nei punti di ingresso main(), nei test e nell'integrazione con codice bloccante.

Quando runBlocking è necessario

runBlocking è giustificato in tre scenari: il punto di ingresso dell'applicazione (main), i test unitari di funzioni suspend e l'integrazione con librerie basate su callback dove suspend non può essere utilizzato. Nel codice Android di produzione, l'uso di runBlocking sul thread principale non è raccomandato.

kotlin
class CoroutineTest {
    @Test
    fun `test suspend function`() = runBlocking {
        val result = mySuspendFunction()
        assertEquals("expected", result)
    }
}

Per i test, si consiglia di utilizzare kotlinx-coroutines-test con TestCoroutineDispatcher invece di runBlocking — questo fornisce controllo del tempo ed evita blocchi nell'ambiente di test.

Come scegliere il costruttore giusto

La scelta del Coroutine Builder dipende dal risultato restituito e dallo scenario di esecuzione. Se l'operazione non richiede la restituzione di dati — usa launch. Se hai bisogno del risultato di un'operazione asincrona — usa async. runBlocking dovrebbe essere usato solo come ponte e sostituisci produce con Flow per i flussi reattivi.

Raccomandazioni pratiche per Android

Nei progetti Android che utilizzano Kotlin Coroutines, la coppia principale di costruttori sono launch e async. launch viene utilizzato in ViewModel e UseCases per avviare coroutine, mentre async viene utilizzato per richieste parallele alla rete o al database. Le librerie moderne (Ktor, Room) supportano già funzioni suspend, il che minimizza la necessità dell'uso diretto di async.

  • launch — per fire-and-forget (logging, analisi, cache)
  • async — per richieste parallele con combinazione dei risultati
  • runBlocking — solo in main() e test (non sul thread Main in produzione)
  • produce — sostituire con Flow / SharedFlow / StateFlow

Domande frequenti

Qual è la differenza tra launch e async in Kotlin?

launch restituisce Job e non restituisce un risultato di esecuzione, mentre async restituisce Deferred<T> — un oggetto da cui ottenere il risultato tramite await(). launch viene usato per operazioni fire-and-forget, async per attività che restituiscono dati.

Si può usare runBlocking in un'Activity Android?

Sconsigliato. runBlocking sul thread principale causa ANR e blocca l'interfaccia. Usa lifecycleScope.launch all'interno di Activity e Fragment — è una soluzione integrata senza blocchi.

Cosa restituisce il costruttore launch?

Il costruttore launch restituisce un oggetto Job, che consente di controllare il ciclo di vita della coroutine: annullare (cancel), attendere il completamento (join), verificare lo stato (isActive, isCompleted, isCancelled).

Cos'è Deferred in Kotlin Coroutines?

Deferred<T> è una promessa asincrona di un risultato, restituita dal costruttore async. Eredita da Job e aggiunge metodi: await() per ottenere il risultato, getCompleted() per accesso non bloccante e getCompletionExceptionOrNull() per verificare le eccezioni.

Come avviare launch con ritardo?

Usa il parametro CoroutineStart.LAZY: scope.launch(start = CoroutineStart.LAZY) { ... }. Quindi chiama job.start() o job.join() per l'esecuzione effettiva. Ciò è utile per l'inizializzazione ritardata e l'esecuzione condizionale delle coroutine.

Riepilogo

  • Coroutine Builder — una funzione di creazione di coroutine che definisce la sua esecuzione e il tipo restituito
  • launch — il costruttore principale per attività senza risultato, restituisce Job per la gestione della coroutine
  • async — costruttore per calcoli paralleli, restituisce Deferred con possibilità di await() del risultato
  • runBlocking — costruttore bloccante per main() e test, sconsigliato sul thread principale Android
  • Concorrenza strutturata garantisce l'annullamento automatico delle coroutine figlie all'annullamento dell'ambito
  • produce è deprecato — usa Flow, SharedFlow o StateFlow per flussi di dati reattivi
  • La scelta del costruttore dipende dallo scenario: fire-and-forget → launch, dati paralleli → async, ponte → runBlocking

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