Jetpack Compose: cos'è, concetti chiave e funzioni Composable

Autore: IT Sectr Pubblicato: 2026-05-01 Tempo di lettura: 9 min

Jetpack Compose è un toolkit dichiarativo moderno per costruire interfacce Android in Kotlin. Lo sviluppatore descrive l'UI tramite funzioni composable e il toolkit ridisegna automaticamente solo le parti modificate. Secondo Android Developers (2026), Jetpack Compose funziona su Android 5.0 (API 21) e superiori, supporta Material Design 3 e raggiunge 120 FPS su dispositivi di fascia media grazie al proprio sistema di Recomposition — un algoritmo diff intelligente che aggiorna solo i widget modificati.

Punti chiave

  • Jetpack Compose — un framework UI dichiarativo per Android dove l'interfaccia è costruita tramite funzioni annotate @Composable in Kotlin.
  • Recomposition — un meccanismo che aggiorna automaticamente solo i componenti i cui dati sono cambiati, offrendo 120 FPS.
  • State è gestito tramite mutableStateOf, collectAsState e StateFlow — quando il valore cambia, la composizione si riavvia per le viste dipendenti.
  • Modifier — una catena di funzioni per configurare padding, dimensioni, sfondo, click e animazioni senza ereditarietà di classi.
  • Side Effects — LaunchedEffect, DisposableEffect e rememberCoroutineScope — gestiscono azioni secondarie: timer, richieste di rete, sottoscrizioni.

Cos'è Jetpack Compose?

Jetpack Compose è un framework dichiarativo di Google per costruire interfacce utente Android, annunciato nel 2019 e arrivato alla versione stabile nel 2021. A differenza del vecchio View System (layout XML + Activity/Fragment), Compose utilizza funzioni Kotlin annotate — @Composable. L'interfaccia è descritta interamente in Kotlin: non c'è separazione tra XML e codice. Questo ha eliminato la classe di errori legati a ID non corrispondenti in XML e Kotlin (type-safe synthetic non aiutava nel refactoring).

Compose è costruito sul proprio sistema di rendering — Canvas, non legato alla gerarchia View. Ogni Composable si disegna direttamente su Canvas, bypassando onMeasure/onDraw del View System. Questo offre un aumento di performance su schermi complessi: nei test di Google (2023), uno schermo Compose con 200 elementi è stato renderizzato il 40% più velocemente di uno simile su RecyclerView + ViewHolder.

Requisiti minimi e compatibilità

Compose richiede minSdk 21 (Android 5.0) e Kotlin 1.9+. Il BOM (Bill of Materials) di Compose sincronizza le versioni di tutte le librerie Compose. Il framework è compatibile con codice View System esistente: Compose si integra tramite ComposeView nei layout XML, e le View vecchie tramite AndroidView nella gerarchia Compose. Secondo Google Play Console (2025), Android 5.0+ copre il 97% dei dispositivi attivi, quindi la compatibilità non è una limitazione per la maggior parte dei progetti.

Funzioni Composable e composizione

@Composable è un'annotazione che trasforma una normale funzione Kotlin in un blocco di costruzione dell'UI. Una funzione Composable descrive come dovrebbe apparire un frammento dell'interfaccia — testo, pulsante, elenco. Invece di restituire un valore, la funzione emette componenti UI nella composizione. È simile a un generatore: ogni funzione aggiunge elementi allo schermo quando viene chiamata.

kotlin
@Composable
fun ProfileCard(name: String, avatarUrl: String) {
    Card(
        modifier = Modifier.fillMaxWidth().padding(16.dp),
        colors = CardDefaults.cardColors(
            containerColor = MaterialTheme.colorScheme.surface
        )
    ) {
        Row(verticalAlignment = Alignment.CenterVertically) {
            AsyncImage(
                model = avatarUrl,
                contentDescription = "Avatar",
                modifier = Modifier.size(48.dp).clip(CircleShape)
            )
            Spacer(Modifier.width(12.dp))
            Text(
                text = name,
                style = MaterialTheme.typography.titleMedium
            )
        }
    }
}

La funzione ProfileCard accetta parametri (name, avatarUrl) ed emette Card → Row → AsyncImage + Text. Composizione è l'albero dei componenti emessi in un unico passaggio. Se i parametri non sono cambiati, Compose salta la chiamata della funzione (recomposition skip). Se solo name è cambiato, verrà chiamato solo Text, gli altri elementi non verranno ridisegnati. Questa ricomposizione intelligente è il vantaggio principale di performance di Compose rispetto all'ottimizzazione manuale del View System.

Slot e Content Lambda

Le funzioni Composable utilizzano attivamente gli slot — trailing lambda, content: @Composable (() -> Unit). Questo permette di creare contenitori: Card, Column, Row accettano una lambda content, e il contenuto viene inserito nello slot. La Slot API ha sostituito attributi XML come android:layout_gravity — ora il posizionamento degli elementi figli è impostato dal codice Kotlin all'interno del blocco di contenuto.

Gestione dello stato in Compose

State in Compose è qualsiasi valore che può cambiare nel tempo. Quando lo stato cambia, Compose pianifica la ricomposizione per tutti i componenti che leggono questo stato. Il meccanismo ricorda gli hook di React: mutableStateOf restituisce MutableState<T>, la lettura di .value sottoscrive automaticamente la composizione corrente ai cambiamenti.

kotlin
@Composable
fun CounterExample() {
    var count by remember { mutableStateOf(0) }

    Column(modifier = Modifier.padding(16.dp)) {
        Text("Cliccato: $count")
        Button(onClick = { count++ }) {
            Text("Incrementa")
        }
    }
}

@Composable
fun UserScreen(viewModel: UserViewModel) {
    val userName by viewModel.userName.collectAsState()
    Text("Utente: $userName")
}

remember preserva il valore tra le ricomposizioni — altrimenti mutableStateOf verrebbe ricreato a ogni aggiornamento dell'UI. collectAsState() converte StateFlow dal ViewModel in uno stato compatibile con Compose. Raccomandazione — utilizzare ViewModel con StateFlow per lo stato a livello di schermo e mutableStateOf per lo stato locale (ad esempio, carta espansa). Questa separazione segue il principio dei componenti intelligenti/muti.

State Hoisting

State Hoisting è un pattern di sollevamento dello stato da un componente figlio al genitore. Il genitore passa il valore e un callback tramite parametri, il figlio chiama il callback al cambiamento. Il genitore mantiene mutableStateOf, il figlio solo i parametri. Questo rende il componente riutilizzabile e testabile: lo stesso TextField può essere usato con qualsiasi fonte di dati.

Modifier — personalizzazione dell'aspetto

Modifier è un oggetto che descrive le trasformazioni del Composable: dimensione, padding, sfondo, gestione dei click, animazione, scorrimento. I modificatori vengono applicati tramite una catena di chiamate: Modifier.fillMaxWidth().padding(16.dp).background(Color.Blue).clickable { }. Ogni chiamata restituisce un nuovo Modifier con la proprietà aggiunta — senza mutazione dell'oggetto originale.

L'ordine dei modificatori è importante. Modifier.padding(16.dp).background(Color.Blue) colora l'area con padding. Modifier.background(Color.Blue).padding(16.dp) colora il rettangolo interno e il padding rimane trasparente. La meccanica assomiglia al modello box CSS: padding prima → background funziona come margin + background; background prima → padding funziona come background + padding interno. Lo sviluppatore deve solo ricordare: padding prima = margine esterno, padding dopo = padding interno.

Modificatori personalizzati

Se i modificatori integrati non sono sufficienti, se ne crea uno personalizzato tramite Modifier.composed { ... } o Modifier.then(). All'interno di un modificatore personalizzato, si possono usare misurazioni di layout (Modifier.layout { measurable, constraints -> ... }), disegno (Modifier.drawWithContent { ... }), gesti (Modifier.pointerInput { ... }). Esempio: un modificatore per animazione pulsante al click — misura la dimensione, al click avvia un'animazione di scala tramite animateFloatAsState.

Per le animazioni, Compose fornisce animate*AsState (animateFloatAsState, animateColorAsState, animateDpAsState) — i valori animano tra stato vecchio e nuovo al cambiamento. Per animazioni di entrata/uscita — AnimatedVisibility e AnimatedContent con transizioni integrate (fade, slide, expand). Tutte le animazioni funzionano sul layer grafico senza innescare composizione non necessaria.

Side Effects: LaunchedEffect, DisposableEffect, remember

Le funzioni Composable non dovrebbero eseguire effetti collaterali direttamente (richieste di rete, timer, sottoscrizioni) — vengono chiamate a ogni ricomposizione, il che porterebbe a richieste duplicate. Per gli effetti collaterali, Compose fornisce una famiglia di funzioni Effect: LaunchedEffect avvia una coroutine all'entrata nella composizione e la cancella all'uscita, DisposableEffect — per risorse che richiedono pulizia esplicita (sensori, BroadcastReceiver).

kotlin
@Composable
fun SensorReader() {
    val context = LocalContext.current
    var sensorValue by remember { mutableStateOf(0f) }

    DisposableEffect(Unit) {
        val sensor = registerSensorListener(context) { value ->
            sensorValue = value
        }
        onDispose {
            unregisterSensorListener(sensor)
        }
    }

    Text("Valore: $sensorValue")
}

@Composable
fun UserGreeting(userId: String) {
    LaunchedEffect(userId) {
        val profile = api.fetchProfile(userId)
        // aggiornamento stato
    }
}

LaunchedEffect(userId) si riavvia se userId cambia — la coroutine precedente viene cancellata e una nuova viene avviata con il nuovo userId. Questo elimina la gestione manuale della cancellazione delle richieste. DisposableEffect(Unit) — un effetto con chiave fissa Unit, si attiva all'entrata nella composizione e chiama onDispose all'uscita. SensorReader registra un listener e si disiscrive quando si lascia lo schermo — senza rischio di perdite.

rememberCoroutineScope

Se è necessario avviare una coroutine non all'entrata nella composizione ma su un evento (click su pulsante), si usa rememberCoroutineScope(). Restituisce un CoroutineScope legato al ciclo di vita del Composable, senza bisogno di DisposableEffect. Esempio: avviare una richiesta di rete al click su un pulsante — scope.launch { viewModel.loadData() }.

Jetpack Compose vs View System: confronto

Scegliere tra Compose e View System è la principale questione architetturale per gli sviluppatori Android nel 2026. Entrambe le tecnologie sono supportate da Google, ma Compose è la direzione principale in cui Google investe risorse. View System riceve solo correzioni critiche e non si evolve. La differenza si manifesta nella sintassi, nella gestione dello stato, nelle performance e nei tempi di sviluppo.

AspettoJetpack ComposeView System
Descrizione UIFunzioni Kotlin @ComposableLayout XML + Activity/Fragment
StatomutableStateOf, StateFlow, ridisegno automaticofindViewById, manuale: setText, notifyDataSetChanged
PerformanceRicomposizione intelligente, rendering CanvasGerarchia View, measure/layout/draw
Animazionianimate*AsState, AnimatedVisibility, integrateValueAnimator, ObjectAnimator, Transition
CompatibilitàminSdk 21, ponti ComposeView/AndroidViewTutte le versioni, qualsiasi
Dimensione APK+3–5 MB per ComposeSenza overhead

Per i nuovi progetti, Google raccomanda Jetpack Compose come standard per lo sviluppo UI. View System rimane per la manutenzione del codice scritto prima del 2021 e per i casi in cui la dimensione minima dell'APK è critica (ad esempio, per mercati emergenti con dispositivi di fascia bassa). Compose riduce il volume di codice UI del 30–50% rispetto a View System grazie alla sua sintassi dichiarativa e alle animazioni integrate.

Domande frequenti

Posso usare Compose in un progetto View System esistente?

Sì, tramite ComposeView nel layout XML. Aggiungi la dipendenza Compose e avvolgi lo schermo o parte di esso in ComposeView { MyComposable() }. La migrazione è schermo per schermo.

Perché il mio Composable si ridisegna troppo spesso?

Il motivo è che lo stato è sollevato troppo in alto o vengono utilizzati oggetti mutabili. Correzione: derivedStateOf per dati derivati e remember per riferimenti stabili.

Come implementare una lista in Compose?

Usa LazyColumn (analogo a RecyclerView). Gli elementi vengono creati e riutilizzati man mano che si scorre. Per liste complesse con diversi tipi di celle — LazyColumn { items(items, key = { it.id }) { ... } }.

Devo imparare View System prima di Compose?

No, puoi iniziare direttamente con Compose. La conoscenza di View System aiuta nella manutenzione del codice legacy, ma Compose è un ecosistema indipendente con la propria documentazione e i propri pattern.

Compose supporta Material 3?

Sì, Material 3 è il tema standard di Compose dal 2023. Si aggiunge tramite implementation("androidx.compose.material3:material3"). Material 2 è considerato obsoleto.

Riepilogo

  • Jetpack Compose — un framework UI dichiarativo per Android dove l'intera interfaccia è scritta in Kotlin tramite funzioni @Composable.
  • Recomposition ridisegna automaticamente solo i componenti modificati, offrendo 120 FPS senza ottimizzazione manuale.
  • State è gestito tramite mutableStateOf, collectAsState e StateFlow; il pattern State Hoisting rende i componenti riutilizzabili.
  • Modifier — una catena di trasformazioni per configurare aspetto, animazioni e comportamento senza ereditarietà di classi.
  • Side Effects (LaunchedEffect, DisposableEffect) isolano le azioni secondarie dalla ricomposizione, prevenendo perdite e richieste duplicate.
  • LazyColumn sostituisce RecyclerView con meno codice e AnimatedVisibility sostituisce catene Animator complesse.
  • Google raccomanda Compose per tutti i nuovi progetti; View System rimane per il codice legacy e i casi in cui la dimensione minima dell'APK è critica.

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