remember — concetti chiave, conservazione dei valori tra le ricomposizioni

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

remember è una funzione in Jetpack Compose che consente di conservare un valore tra le ricomposizioni, impedendo il ripristino dello stato a ogni riavvio di una funzione Composable. Senza remember, tutte le variabili dichiarate all'interno di una funzione verrebbero reimpostate a ogni aggiornamento dell'interfaccia utente, rendendo lo stato instabile e inutile. Secondo Google Android Developers, 2026, l'uso corretto di remember è il fondamento di una corretta gestione dello stato nelle UI dichiarative.

Punti Chiave

  • remember conserva un valore nello slot di composizione tra le ricomposizioni della funzione
  • Le chiavi in remember(key) determinano quando il valore deve essere ricalcolato
  • rememberSaveable conserva il valore durante la rotazione dello schermo e la minimizzazione dell'app
  • derivedStateOf crea stato derivato, ottimizzando i calcoli durante la ricomposizione
  • Il ripristino di remember avviene solo quando la funzione esce dalla composizione

Cos'è remember in Jetpack Compose

remember è una funzione integrata di Jetpack Compose del pacchetto androidx.compose.runtime che crea un oggetto che conserva il suo valore tra chiamate successive di una funzione Composable. Tecnicamente, remember funziona con slot — celle di memoria speciali allocate per ogni posizione di chiamata di funzione nell'albero UI. Finché la funzione rimane nella composizione (non rimossa tramite una condizione if), remember restituirà il valore salvato a ogni ricomposizione.

La sintassi di remember è semplice: all'interno delle parentesi graffe si specifica il blocco di calcolo del valore iniziale. Il blocco viene eseguito una sola volta — durante la prima composizione della funzione. Tutte le ricomposizioni successive restituiscono il valore già salvato senza rieseguire il blocco. Tuttavia, se viene specificato un parametro chiave, il blocco viene rieseguito quando la chiave cambia, consentendo di ricalcolare il valore in base ai dati di input.

remember non è magia di Kotlin — è una funzione semplice con un parametro chiave e una lambda di calcolo. La sua implementazione interna utilizza Composer per leggere e scrivere negli slot. Il compilatore Kotlin, vedendo una chiamata a remember, genera codice che accede al CompositionContext corrente e gestisce gli slot. Ciò significa che remember può essere chiamato solo all'interno di una funzione Composable o di un'altra funzione nel contesto di composizione.

Tipi di remember: remember, rememberSaveable, derivedStateOf

In Jetpack Compose, esistono tre varianti principali di remember, ciascuna con il proprio scopo. Il remember base conserva il valore solo nella memoria del processo corrente — durante la rotazione dello schermo (cambio configurazione), Compose ricrea la Composition e tutti i valori di remember vengono reimpostati. Per conservare i dati durante i cambi di configurazione e l'arresto del processo si usa rememberSaveable.

rememberSaveable serializza il valore in un Bundle tramite il meccanismo SavedStateHandle o Parcelable. Ciò consente di sopravvivere alla rotazione dello schermo, all'impostazione "Non mantenere attività" e persino alla minimizzazione temporanea dell'app. Tuttavia, rememberSaveable impone restrizioni sul tipo di dati che può memorizzare: devono essere primitivi, Parcelable, Serializable o supportare un convertitore Saver.

derivedStateOf non è un meccanismo di conservazione ma un'ottimizzazione. Crea uno State il cui valore viene calcolato da altri oggetti State. derivedStateOf reagisce ai cambiamenti negli stati sorgente ma ricalcola il valore solo quando ci sono abbonati. Se la ricomposizione corrente non legge derivedStateOf, il calcolo non viene eseguito, risparmiando risorse su aggiornamenti frequenti ma non necessari.

kotlin
@Composable
fun RememberVariants() {
    // 1. Remember base: persiste fino all'uscita dalla composizione
    val createdAt = remember { System.currentTimeMillis() }

    // 2. rememberSaveable: sopravvive alla rotazione dello schermo
    var username by rememberSaveable { mutableStateOf("") }

    // 3. derivedStateOf: calcolato solo quando necessario
    val isButtonVisible = remember {
        derivedStateOf { username.length() > 3 }
    }

    Text("Creato: $createdAt")
    TextField(value = username, onValueChange = { username = it })

    if (isButtonVisible.value) {
        Text("Il pulsante verrà mostrato")
    }
}

remember vs rememberSaveable: quando usare cosa

La scelta tra remember e rememberSaveable dipende da quanto sia critico conservare i dati durante i cambi di configurazione. Per stati temporanei di cui non è importante perdere durante la rotazione (animazione, posizione di scorrimento corrente, stato del focus) — il remember normale è sufficiente. Per dati critici (testo nei moduli, elementi selezionati, caselle di controllo) — usa rememberSaveable.

Prestazioni: rememberSaveable è più lento del remember normale perché richiede la serializzazione in un Bundle. Usa rememberSaveable solo per dati che devono realmente sopravvivere alla ricreazione dell'Activity. Per tutto il resto — remember semplice. L'uso eccessivo di rememberSaveable causa rallentamenti durante la rotazione dello schermo e il passaggio tra app.

Se lavori con classi che non supportano Parcelable o Serializable, usa Saver — un convertitore che definisce come salvare e ripristinare l'oggetto. Saver è descritto da una coppia di lambda: save (converte l'oggetto in un tipo salvabile) e restore (ripristina l'oggetto dai dati salvati). Un Saver standard è già implementato per mutableStateListOf e mutableStateMapOf.

CaratteristicarememberrememberSaveable
Conservazione durante la ricomposizione
Conservazione durante la rotazioneNo
Conservazione durante l'arresto del processoNo
Requisiti di tipoQualsiasiParcelable, Serializable, Saver
PrestazioniAlteMedie

Esempi di utilizzo di remember in progetti reali

Consideriamo uno scenario tipico — una schermata di modifica del profilo in cui remember viene utilizzato per diversi scopi: memorizzare lo stato dei campi del modulo, calcolare valori derivati e memorizzare nella cache operazioni computazionalmente costose.

kotlin
data class ProfileUiState(
    val name: String = "",
    val bio: String = "",
    val isSaving: Boolean = false
)

@Composable
fun ProfileEditor() {
    var state by rememberSaveable { mutableStateOf(ProfileUiState()) }
    val isValid = remember {
        derivedStateOf { state.name.isNotBlank() && state.bio.length() <= 500 }
    }

    val bioWarning = remember(state.bio) {
        if (state.bio.length() > 400) {
            "${500 - state.bio.length} chars left"
        } else null
    }

    Column(modifier = Modifier.padding(16.dp)) {
        OutlinedTextField(
            value = state.name,
            onValueChange = { state = state.copy(name = it) },
            label = { Text("Nome") }
        )

        OutlinedTextField(
            value = state.bio,
            onValueChange = { state = state.copy(bio = it) },
            label = { Text("Informazioni") }
        )

        bioWarning?.let { Text(it, color = MaterialTheme.colorScheme.error) }

        Button(onClick = { /* save */ },
            enabled = isValid.value) {
            Text("Salva")
        }
    }
}

Nell'esempio, lo stato viene salvato tramite rememberSaveable — il testo non andrà perso durante la rotazione dello schermo. isValid viene calcolato tramite derivedStateOf, che impedisce calcoli non necessari durante le ricomposizioni. bioWarning usa remember con la chiave bio — questo è un calcolo costoso (opzionale, per dimostrazione) che viene ricalcolato solo quando bio cambia, non a ogni ricomposizione.

Stati derivati e remember con chiavi

Gli stati derivati sono valori calcolati da altri oggetti State. Invece di calcolarli a ogni ricomposizione e sprecare CPU su risultati identici, remember con derivedStateOf calcola il valore solo quando le fonti cambiano. Questo è particolarmente utile per filtraggio, ordinamento e aggregazione di dati.

remember con chiavi (remember(key) { calculation }) è un altro meccanismo di ottimizzazione. Se la chiave non è cambiata dall'ultima ricomposizione, il blocco di calcolo non viene eseguito e viene restituito il valore memorizzato nella cache. Questo è comodo per memorizzare nella cache oggetti la cui creazione è costosa: formattazione di date, analisi JSON, creazione di grandi collezioni immutabili.

kotlin
@Composable
fun SearchResults(allItems: List<Item>, query: String) {
    // derivedStateOf: filtro ricalcolato solo quando gli input cambiano
    val filtered = remember {
        derivedStateOf {
            allItems.filter { it.title.contains(query, true) }
        }
    }

    // remember con chiave: statistiche formattate ricalcolate solo al cambio della query
    val statsText = remember(query) {
        "Results for query \"$query\": ${filtered.value.size}"
    }

    Text(statsText)
    LazyColumn {
        items(filtered.value, key = { it.id }) { item ->
            Text(item.title)
        }
    }
}

filtered è un derivedStateOf che si ricalcola automaticamente quando allItems o query cambiano. statsText usa remember(query) — la costosa formattazione di stringhe viene eseguita solo quando la query di ricerca cambia. La combinazione di derivedStateOf e remember con chiavi offre le massime prestazioni: lo stato derivato viene calcolato solo quando necessario e gli oggetti complessi vengono memorizzati nella cache fino a quando la chiave non cambia.

Domande Frequenti

Si può usare remember al di fuori di una funzione Composable?

No, remember è una funzione del pacchetto compose.runtime che richiede un CompositionContext. Può essere chiamata solo all'interno di una funzione @Composable o all'interno di un'altra funzione chiamata da una Composable. Per memorizzare dati al di fuori della composizione, usa ViewModel.

Cosa succede se non si specifica una chiave in remember?

Senza chiave, remember esegue il blocco di calcolo una sola volta — durante la prima composizione. Tutte le ricomposizioni successive restituiscono il valore salvato. Se devi ricalcolare il valore quando i dati cambiano, assicurati di specificarli come chiave: remember(data) { compute(data) }.

Come forzare il ripristino di remember?

Non esiste un modo diretto per ripristinare remember. L'unico modo è rimuovere la funzione dalla composizione (ad esempio, nascondendola con una condizione if) e poi mostrarla di nuovo. Al rientro, il blocco remember viene eseguito di nuovo, creando un nuovo valore iniziale.

Qual è la differenza tra remember e ViewModel?

remember memorizza lo stato in uno slot di funzione Composable e vive finché la funzione è nella composizione. ViewModel vive finché dura il ciclo di vita dello schermo. ViewModel viene conservato durante la rotazione e viene utilizzato per la logica di business. remember è per lo stato UI locale che non serve al di fuori di una singola funzione.

Remember funziona nei componenti Preview?

Sì, remember funziona correttamente nelle funzioni @Preview Composable perché Preview crea un CompositionContext completo. Tuttavia, rememberSaveable potrebbe non funzionare correttamente in Preview poiché SavedStateHandle potrebbe essere assente nell'ambiente di anteprima.

Riepilogo

  • remember conserva un valore nello slot di composizione e sopravvive alle ricomposizioni della funzione
  • rememberSaveable conserva inoltre il valore durante la rotazione dello schermo e l'arresto del processo
  • derivedStateOf crea stato derivato con calcoli pigri
  • Le chiavi in remember(key) controllano il ricalcolo del valore nella cache
  • Il ripristino di remember avviene solo quando la funzione viene rimossa dalla composizione
  • Prestazioni: derivedStateOf e le chiavi prevengono calcoli non necessari durante la ricomposizione
  • Raccomandazione: usa rememberSaveable per i campi di input e remember + derivedStateOf per i valori calcolati

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