remember — is een functie in Jetpack Compose die een waarde kan behouden tussen recomposities, waardoor wordt voorkomen dat de status bij elke herstart van een Composable-functie wordt gereset. Zonder remember zouden alle variabelen die binnen de functie zijn gedeclareerd bij elke UI-update worden gereset, waardoor de status instabiel en nutteloos wordt. Volgens Google Android Developers, 2026 is correct gebruik van remember de basis voor correct statusbeheer in declaratieve UI.
Belangrijkste punten
remember — is een ingebouwde functie van Jetpack Compose uit het pakket androidx.compose.runtime die een object creëert dat zijn waarde behoudt tussen opeenvolgende aanroepen van de Composable-functie. Technisch werkt remember met slots — speciale geheugencellen die zijn toegewezen aan elke aanroeppositie van de functie in de UI-boom. Zolang de functie in de compositie blijft (niet verwijderd via een if-voorwaarde), zal remember bij elke recompositie de opgeslagen waarde teruggeven.
De syntax van remember is eenvoudig: tussen accolades wordt het berekeningsblok voor de beginwaarde opgegeven. Het blok wordt slechts één keer uitgevoerd — bij de eerste compositie van de functie. Alle volgende recomposities geven de reeds opgeslagen waarde terug zonder het blok opnieuw aan te roepen. Als er echter een sleutel (parameter key) is opgegeven, wordt het blok opnieuw uitgevoerd wanneer de sleutel verandert, waardoor de waarde op basis van invoergegevens opnieuw kan worden berekend.
remember is geen Kotlin-magie — het is een eenvoudige functie met een key-parameter en een berekeningslambda. De interne implementatie gebruikt Composer om in slots te lezen en te schrijven. De Kotlin-compiler genereert bij het zien van een remember-aanroep code die toegang krijgt tot de huidige CompositionContext en de slots beheert. Dit betekent dat remember alleen binnen een Composable-functie of een andere functie in de compositiecontext kan worden aangeroepen.
In Jetpack Compose zijn er drie hoofdvariëteiten van remember, elk met hun eigen doel. Basis remember behoudt de waarde alleen in het geheugen van het huidige proces — bij schermrotatie (config change) maakt Compose de Composition opnieuw en worden alle remember-waarden gereset. Voor het behouden van gegevens bij configuratiewijzigingen en het stoppen van het proces wordt rememberSaveable gebruikt.
rememberSaveable serialiseert de waarde naar Bundle via het SavedStateHandle- of Parcelable-mechanisme. Dit maakt het mogelijk om schermrotatie, de aanroep “Activiteiten niet bewaren” en zelfs tijdelijk minimaliseren van de app te overleven. Echter, rememberSaveable legt beperkingen op aan het type gegevens dat kan worden opgeslagen: ze moeten primitieven, Parcelable, Serializable zijn of de Saver-converter ondersteunen.
derivedStateOf — is geen opslagmechanisme, maar een optimalisatie. Het creëert een State waarvan de waarde wordt berekend op basis van andere State-objecten. derivedStateOf reageert op veranderingen in bronstatussen, maar herberekent de waarde alleen wanneer er abonnees zijn. Als de huidige recompositie derivedStateOf niet leest, wordt de berekening niet uitgevoerd, wat resources bespaart bij frequente maar onnodige updates.
@Composable
fun RememberVariants() {
// 1. Basis remember: blijft tot het verlaten van de compositie
val createdAt = remember { System.currentTimeMillis() }
// 2. rememberSaveable: overleeft schermrotatie
var username by rememberSaveable { mutableStateOf("") }
// 3. derivedStateOf: alleen berekend wanneer nodig
val isButtonVisible = remember {
derivedStateOf { username.length() > 3 }
}
Text("Aangemaakt: $createdAt")
TextField(value = username, onValueChange = { username = it })
if (isButtonVisible.value) {
Text("Knop wordt getoond")
}
}
De keuze tussen remember en rememberSaveable hangt af van hoe kritiek het behouden van gegevens bij configuratiewijzigingen is. Voor tijdelijke statussen waarvan het verlies bij rotatie niet belangrijk is (animatie, huidige scrollpositie, focusstatus) — is gewone remember voldoende. Voor kritieke gegevens (tekst in formulieren, geselecteerde items, checkboxes) — gebruik rememberSaveable.
Prestaties van rememberSaveable zijn lager dan die van gewone remember, omdat serialisatie naar Bundle nodig is. Gebruik rememberSaveable alleen voor gegevens die het opnieuw aanmaken van Activity moeten overleven. Voor al het andere — gewone remember. Overmatig gebruik van rememberSaveable leidt tot vertragingen bij schermrotaties en het schakelen tussen apps.
Als u werkt met klassen die Parcelable of Serializable niet ondersteunen, gebruik dan Saver — een converter die bepaalt hoe een object moet worden opgeslagen en hersteld. Saver wordt beschreven door een paar lambda's: save (zet het object om naar een opslagbaar type) en restore (herstelt het object uit opgeslagen gegevens). De standaard Saver is al geïmplementeerd voor mutableStateListOf en mutableStateMapOf.
| Kenmerk | remember | rememberSaveable |
|---|---|---|
| Behoud bij recompositie | Ja | Ja |
| Behoud bij rotatie | Nee | Ja |
| Behoud bij stoppen proces | Nee | Ja |
| Typevereisten | Elk | Parcelable, Serializable, Saver |
| Prestaties | Hoog | Gemiddeld |
Laten we een typisch scenario bekijken — het profielbewerkingsscherm, waar remember voor meerdere doeleinden wordt gebruikt: het opslaan van de status van formuliervelden, het berekenen van afgeleide waarden en het cachen van rekenintensieve bewerkingen.
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("Naam") }
)
OutlinedTextField(
value = state.bio,
onValueChange = { state = state.copy(bio = it) },
label = { Text("Over") }
)
bioWarning?.let { Text(it, color = MaterialTheme.colorScheme.error) }
Button(onClick = { /* save */ },
enabled = isValid.value) {
Text("Opslaan")
}
}
}
In het voorbeeld wordt de status opgeslagen via rememberSaveable — bij schermrotatie gaat de tekst niet verloren. isValid wordt berekend via derivedStateOf, wat onnodige berekeningen bij recomposities voorkomt. bioWarning gebruikt remember met de sleutel bio — dit is een dure berekening (optioneel, ter demonstratie) die alleen opnieuw wordt berekend bij wijziging van bio, niet bij elke recompositie.
Afgeleide statussen (derived state) zijn waarden die worden berekend uit andere State-objecten. In plaats van ze bij elke recompositie te berekenen en CPU te verspillen aan identieke resultaten, berekent remember met derivedStateOf de waarde alleen wanneer de bronnen veranderen. Dit is vooral nuttig voor filteren, sorteren en aggregeren van gegevens.
remember met sleutels (remember(key) { calculation }) — een ander optimalisatiemechanisme. Als de sleutel niet is veranderd sinds de vorige recompositie, wordt het berekeningsblok niet uitgevoerd en wordt de gecachte waarde teruggegeven. Dit is handig voor het cachen van objecten waarvan het aanmaken duur is: datumopmaak, JSON-parsing, het maken van grote onveranderlijke verzamelingen.
@Composable
fun SearchResults(allItems: List<Item>, query: String) {
// derivedStateOf: filter wordt alleen herberekend wanneer invoer verandert
val filtered = remember {
derivedStateOf {
allItems.filter { it.title.contains(query, true) }
}
}
// remember met sleutel: opgemaakte statistieken alleen herberekend bij wijziging van 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 — is een derivedStateOf dat automatisch opnieuw wordt berekend bij wijziging van allItems of query. statsText gebruikt remember(query) — dure tekenreeksopmaak wordt alleen uitgevoerd bij wijziging van de zoekopdracht. De combinatie van derivedStateOf en remember met sleutels geeft maximale prestaties: de afgeleide status wordt alleen berekend wanneer nodig, en complexe objecten worden gecacht tot de sleutel verandert.
Veelgestelde vragen
Nee, remember — is een functie uit het pakket compose.runtime die CompositionContext vereist. Het kan alleen worden aangeroepen binnen een @Composable-functie of binnen een andere functie die vanuit Composable wordt aangeroepen. Voor het opslaan van gegevens buiten de compositie gebruikt u ViewModel.
Zonder sleutel berekent remember het blok slechts één keer — bij de eerste compositie. Alle volgende recomposities geven de opgeslagen waarde terug. Als u de waarde opnieuw wilt berekenen bij verandering van gegevens, geef deze dan op als sleutel: remember(data) { compute(data) }.
Er is geen directe reset van remember. De enige manier is om de functie uit de compositie te verwijderen (bijvoorbeeld door te verbergen via een if-voorwaarde) en deze vervolgens opnieuw weer te geven. Bij hernieuwde invoer wordt het remember-blok opnieuw uitgevoerd, waardoor een nieuwe beginwaarde ontstaat.
remember slaat de status op in de slot van de Composable-functie en leeft zolang de functie in de compositie is. ViewModel leeft zolang de lifecycle van het scherm leeft. ViewModel blijft behouden bij rotatie en wordt gebruikt voor bedrijfslogica. remember — voor lokale UI-status die niet buiten één functie nodig is.
Ja, remember werkt correct in @Preview Composable-functies, omdat Preview een volledige CompositionContext creëert. Echter, rememberSaveable werkt mogelijk niet correct in Preview, omdat SavedStateHandle mogelijk ontbreekt in de preview-omgeving.
Samenvatting
We ontwikkelen een mobiele applicatie turnkey
IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.
Lees ook