Composition: essenza, costruzione dell'albero UI in Compose

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

Composition è il processo centrale in Jetpack Compose, durante il quale un albero UI vivo visualizzato sullo schermo viene costruito da funzioni Composable descrittive. A differenza del sistema View di Android, dove i layout venivano caricati da XML e convertiti in oggetti immutabili, Composition funziona come un sistema dinamico: le funzioni vengono eseguite, creano slot in memoria, formano una gerarchia di nodi e la legano allo stato. Secondo Google Android Developers, 2026, comprendere Composition è fondamentale per ottimizzare le prestazioni delle applicazioni Compose.

Punti chiave

  • Composition è l'esecuzione di funzioni Composable per costruire l'albero UI
  • Slot sono celle di memoria che memorizzano parametri e stato di ogni funzione
  • Posizione in Compose (Positional Memorization) lega lo stato a una posizione nel codice
  • Primo passaggio Composition crea l'albero UI iniziale all'avvio dello schermo
  • CompositionLocal passa dati attraverso l'albero senza parametri espliciti

Cos'è Composition in Jetpack Compose

Composition è il processo di esecuzione delle funzioni Composable, che risulta in una rappresentazione interna dell'interfaccia utente come albero di nodi. Ogni nodo di questo albero corrisponde a un componente integrato (Text, Button, Image) o a una chiamata a una funzione Composable definita dall'utente. Composition non crea direttamente oggetti View Android — costruisce una descrizione astratta che viene poi elaborata dalle fasi Layout e Drawing.

La caratteristica principale di Composition è la sua riavviabilità. Ogni funzione Composable all'interno della composizione può essere riavviata in qualsiasi momento se i suoi parametri di input o gli oggetti di stato che legge sono cambiati. Il sistema non riavvia l'intero albero — solo quelle funzioni che dipendono effettivamente dai dati modificati.

Tecnicamente, Composition è gestita tramite Composer — un motore interno che il compilatore Kotlin incorpora in ogni funzione Composable. Composer scrive in slot (gruppi di posizione) informazioni su quali funzioni sono state chiamate, con quali parametri e in quale ordine. Nelle chiamate successive, Composer confronta i nuovi dati con i dati memorizzati e decide se riavviare.

Come viene costruito l'albero UI durante Composition

Il processo di costruzione dell'albero UI inizia con la chiamata del metodo setContent all'interno di un'Activity o Fragment. Questo metodo crea la Composition iniziale e avvia l'esecuzione della funzione Composable radice. Quindi ogni funzione Composable annidata aggiunge i propri nodi all'albero, formando una gerarchia: Row contiene Text e Button, Column contiene Image e Card, e così via.

Ogni nodo dell'albero riceve una chiave di posizione unica, basata sulla sua posizione nel codice sorgente. Questa chiave viene utilizzata per identificare il nodo durante le esecuzioni successive. La chiave di posizione è il motivo per cui l'ordine di chiamata delle funzioni Composable non deve dipendere da condizioni: se in un'esecuzione viene chiamato A -> B, e nella successiva B -> A, Compose non sarà in grado di far corrispondere i nodi vecchi e nuovi.

kotlin
@Composable
fun AppScreen() {
    Column {                     // Nodo Column (posizione 1)
        HeaderSection()            // Nodo HeaderSection (posizione 2)
        ContentSection()           // Nodo ContentSection (posizione 3)
        FooterSection()            // Nodo FooterSection (posizione 4)
    }
}

@Composable
fun HeaderSection() {
    Row {                       // Nodo Row (posizione 2.1)
        Text("Titolo")         // Nodo Text (posizione 2.2)
        Icon(...)                // Nodo Icon (posizione 2.3)
    }
}

In questo esempio, ogni chiamata riceve una posizione basata sull'ordine nel codice. Column (posizione 1) contiene tre nodi figli (posizioni 2, 3, 4). HeaderSection aggiunge altri due nodi figli (2.1, 2.2, 2.3). Se nella prossima ricomposizione ContentSection viene chiamato prima di HeaderSection, Composer non sarà in grado di far corrispondere correttamente i nodi — da qui la regola: l'ordine delle chiamate alle funzioni Composable deve essere stabile.

Gestione dello stato in Composition

Lo stato in Composition è gestito tramite oggetti di tipo State<T>. Quando una funzione Composable legge un valore da State tramite una proprietà delegata (by), registra una dipendenza da quello State. Quando il valore cambia, tutte le funzioni che hanno letto questo State vengono contrassegnate per il riavvio nella fase di composizione successiva.

Il meccanismo di registrazione delle dipendenze si chiama sistema di snapshot. Ogni volta che State cambia, uno snapshot registra tutte le modifiche e notifica a Composer quali funzioni dipendono da quello State. È importante capire: leggere State all'interno di codice non-Composable (ad esempio, in una lambda onClick) non registra una dipendenza — solo la lettura all'interno di una funzione Composable o in lambda eseguite nel contesto di composizione.

Il sistema di snapshot funziona in modo transazionale: più modifiche di State all'interno di un singolo evento vengono combinate in un'unica transazione, prevenendo molteplici ricomposizioni. Questo è particolarmente importante nella gestione dei gesti: un movimento modifica diversi oggetti State, ma Compose esegue una sola ricomposizione.

kotlin
@Composable
fun StateExample() {
    var text by remember { mutableStateOf("Hello") }
    var isVisible by remember { mutableStateOf(true) }

    Column {
        Text(text)  // registra dipendenza da text

        if (isVisible) {  // registra dipendenza da isVisible
            TextField(value = text, onValueChange = { text = it })
        }

        Button(onClick = { isVisible = !isVisible }) {
            Text(if (isVisible) "Nascondi" else "Mostra")
        }
    }
}

Cambiare text attiva la ricomposizione solo di Column, Text e TextField. Column, Button e la condizione isVisible rimangono invariati. Questo isolamento della ricomposizione è un vantaggio chiave di Compose rispetto ai sistemi che ridisegnano l'intero schermo. Ogni funzione Composable traccia solo gli oggetti State che legge direttamente.

Composition vs Recomposition: differenze chiave

Composition e Recomposition sono due diverse modalità di esecuzione delle funzioni Composable. Composition avviene una volta quando lo schermo viene creato: il sistema esegue tutte le funzioni Composable con valori iniziali e costruisce l'albero UI iniziale. Recomposition avviene più volte quando i dati cambiano: il sistema riavvia solo le funzioni che dipendono dallo stato modificato.

Modalità Composition attiva tutti i nodi dell'albero, alloca slot per ogni funzione e registra tutti i discendenti. Recomposition funziona selettivamente: Compose confronta i nuovi e vecchi valori dei parametri di ogni funzione, e se non sono cambiati — la funzione non viene eseguita (skipping).

Composition e Recomposition differiscono in costo. La prima Composition è più costosa perché richiede la costruzione completa dell'albero e l'allocazione degli slot. Recomposition è più economica, specialmente se la maggior parte delle funzioni è stabile — i loro parametri vengono confrontati con equals, e Compose salta la loro invocazione. Per le massime prestazioni, bisogna cercare di far sì che la maggior parte delle ricomposizioni interessi il minor numero possibile di funzioni.

CaratteristicaCompositionRecomposition
Quando avvieneUna volta, al primo displayPiù volte, al cambio di dati
AmbitoIntero alberoSolo funzioni modificate
Confronto parametriNon eseguitoEseguito per skipping
Creazione slotSì, tutti gli slot creatiSolo per nuovi nodi

CompositionLocal: passaggio di dati attraverso l'albero

CompositionLocal è un meccanismo per passare dati implicitamente attraverso l'albero di composizione. Risolve il problema quando un parametro deve essere passato attraverso decine di funzioni Composable annidate che non lo usano direttamente. Invece di una catena esplicita di parametri, i dati vengono impostati al livello superiore e letti in qualsiasi funzione annidata tramite CompositionLocal.current.

MaterialTheme è l'esempio più noto di CompositionLocal. Tutti i componenti Compose leggono colori, tipografia e forme tramite MaterialTheme.colorScheme, MaterialTheme.typography, MaterialTheme.shapes, senza riceverli tramite parametri. Gli sviluppatori possono creare propri CompositionLocal per dati come l'utente corrente, le impostazioni di localizzazione o la configurazione dello schermo.

Un'importante limitazione: CompositionLocal non dovrebbe essere usato per dati che cambiano frequentemente (posizione di scorrimento, testo in un campo di input). Un componente che legge CompositionLocal si riavvia ogni volta che il valore cambia, quindi per dati dinamici è meglio usare parametri espliciti o State. CompositionLocal è ottimale per dati di configurazione che cambiano raramente o mai.

kotlin
val LocalUser = compositionLocalOf<User?> { null }

@Composable
fun AppRoot(user: User, content: @Composable () -> Unit) {
    CompositionLocalProvider(LocalUser.provides(user)) {
        content()
    }
}

@Composable
fun UserAvatar() {
    val user = LocalUser.current  // lettura senza parametro esplicito
    AsyncImage(model = user?.avatarUrl, contentDescription = "Avatar")
}

CompositionLocalProvider crea un ambito all'interno del quale LocalUser.current restituisce il valore specificato. UserAvatar legge l'utente senza passare esplicitamente il parametro attraverso funzioni intermedie. Questo è particolarmente prezioso in gerarchie profonde dove i dati sono necessari solo in pochi nodi foglia.

Domande frequenti

Cosa succede se State viene modificato durante Composition

Modificare State durante Composition pianifica una nuova ricomposizione, che verrà eseguita dopo il completamento di quella corrente. Non si verifica un ciclo infinito: Compose garantisce che ogni ricomposizione venga eseguita in una transazione separata del sistema di snapshot.

Quanto tempo richiede Composition di uno schermo complesso

Sui dispositivi moderni, la Composition di uno schermo con 50–100 funzioni Composable richiede 1–5 ms. Google raccomanda di rimanere entro 16 ms per un fotogramma a 60fps. Se Composition supera questo limite, utilizzare LazyColumn o suddividere lo schermo in funzioni più piccole.

Può Composition essere avviata manualmente

L'avvio manuale diretto di Composition non è possibile — è gestito da Composer automaticamente. Tuttavia, è possibile forzare una ricomposizione modificando State o chiamando invalidate() sul composable radice se si ha accesso a CompositionContext.

In cosa Composition differisce dalla gerarchia View nell'Android classico

La gerarchia View è un albero immutabile di oggetti Java che viene creato una volta. Composition è un albero virtuale che viene ricostruito ogni volta che i dati cambiano. View memorizza il suo stato in variabili d'istanza, Composition — in slot legati alla posizione della chiamata della funzione.

Come Composition gestisce la rimozione dei nodi

Se una funzione Composable non viene più chiamata (ad esempio, una condizione if diventa false), Composition rimuove il suo nodo e attiva la pulizia di DisposableEffect. Quando riappare (if diventa di nuovo true), viene creato un nuovo nodo — quello vecchio non viene ripristinato.

Riepilogo

  • Composition è il processo di esecuzione di funzioni Composable per costruire un albero UI legato allo stato
  • Composer gestisce gli slot, registra le chiamate alle funzioni e confronta i parametri durante la ricomposizione
  • Sistema di snapshot registra le dipendenze delle funzioni da State e combina le modifiche in transazioni
  • Composition viene eseguita una volta all'avvio, Recomposition — al cambio di dati
  • CompositionLocal passa dati di configurazione attraverso l'albero senza una catena esplicita di parametri
  • Posizione di una chiamata di funzione funge da identificatore univoco nell'albero di composizione
  • Raccomandazione: mantenere le funzioni Composable piccole con parametri immutabili per uno skipping efficiente

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