Recomposition is een mechanisme van Jetpack Compose dat automatisch delen van de gebruikersinterface herbouwt bij gegevenswijziging, zonder handmatige bijwerking van View-elementen. Wanneer een toestandsvariabele waarvan een Composable-functie afhangt van waarde verandert, herstart Compose alleen die functie, terwijl de rest van de UI-boom onaangetast blijft. Volgens Google Android Developers, 2026 stelt correct begrip van Recomposition in staat om het aantal onnodige hertekeningen met 40–60% te verminderen.
Belangrijkste punten
Recomposition is het opnieuw uitvoeren van Composable-functies die al hebben deelgenomen aan Composition, met nieuwe waarden van parameters of toestand. Het hoofddoel van hercompositie is het synchroniseren van de UI-boom met actuele gegevens zonder de hele interface vanaf nul te herbouwen. In tegenstelling tot Composition, dat eenmalig plaatsvindt, kan Recomposition honderden keren worden gestart tijdens de levensduur van een scherm.
Recomposition werkt volgens het principe van smart invalidation: Compose houdt bij welke State-objecten elke Composable-functie leest en markeert voor herstart alleen die waarvan de afhankelijkheden zijn gewijzigd. Dit wordt bereikt door het snapshot-systeem, dat alle leesbewerkingen van State tijdens uitvoering registreert, en Composer, die deze afhankelijkheden aan specifieke functies koppelt.
Het is belangrijk te begrijpen: hercompositie betekent niet onmiddellijke hertekening van het scherm. Compose werkt in drie fasen: Composition (opbouwen van UI-beschrijving), Layout (berekenen van afmetingen en posities) en Drawing (tekenen op het canvas). Als na hercompositie de afmetingen en positie van elementen niet zijn gewijzigd, kan de Layout-fase worden overgeslagen. Als het uiterlijk niet is gewijzigd — wordt Drawing overgeslagen. Deze driefasenarchitectuur zorgt voor minimale kosten van elke UI-bijwerking.
Er zijn drie hoofdtriggers van hercompositie. De eerste — wijziging van het State-object dat in het lichaam van een Composable-functie is gelezen. Wanneer mutableStateOf of derivedStateOf zijn waarde verandert, worden alle functies die het lezen van deze State in de vorige compositie hebben geregistreerd, gemarkeerd voor herstart.
De tweede trigger — wijziging van parameters van de Composable-functie bij aanroep uit de bovenliggende functie. Als de bovenliggende functie een nieuwe waarde heeft doorgegeven (bijvoorbeeld tekst of getal is gewijzigd), wordt de onderliggende functie herstart, zelfs als deze geen State binnenin leest. Compose vergelijkt nieuwe en oude parameterwaarden via equals, en als ze gelijk zijn — kan de functie worden overgeslagen.
De derde trigger — wijziging van CompositionLocal via CompositionLocalProvider. Alle functies die CompositionLocal via .current lezen, worden herstart bij wijziging van de provider. Dit mechanisme wordt gebruikt door MaterialTheme: wijziging van thema (licht/donker) veroorzaakt hercompositie van alle componenten die MaterialTheme.colorScheme lezen.
@Composable
fun RecompositionDemo() {
var counter by remember { mutableStateOf(0) }
var text by remember { mutableStateOf("Hello") }
Column {
Text("Teller: $counter") // hercompositie wanneer teller verandert
Text("Bericht: $text") // hercompositie wanneer tekst verandert
Button(onClick = { counter++ }) {
Text("+1")
}
Button(onClick = { text = "Wereld" }) {
Text("Tekst wijzigen")
}
}
}
Indrukken van de knop +1 verandert counter, wat alleen hercompositie veroorzaakt van de eerste Text-regel en de Column zelf. De tweede Text-regel, die text weergeeft, wordt niet herstart. Zulke isolatie — resultaat van het snapshot-systeem: elke Composable-functie weet alleen van die State-objecten die het heeft gelezen.
Optimalisatie van hercompositie begint met correcte keuze van gegevensstructuren. Gebruik onveranderlijke collecties (listOf, mapOf) in plaats van veranderlijke (mutableListOf). Compose vergelijkt parameters via equals, en als de collectie is gewijzigd maar equals true heeft teruggegeven — wordt de functie niet herstart. Voor veranderlijke collecties gebruikt u SnapshotStateList, dat correcte wijzigingsregistratie op elementniveau implementeert.
De tweede techniek — uithalen van stabiele delen van UI in aparte Composable-functies. Als een deel van het scherm niet afhangt van vaak veranderende toestand, haal het dan in een aparte functie met parameters. Wanneer hercompositie komt, krijgt de stabiele functie dezelfde parameters, Compose vergelijkt ze en slaat uitvoering over. Dit is voordeliger dan dit deel te herstarten binnen een grote functie waar een deel van de parameters is gewijzigd.
De derde techniek — sleutels in LazyColumn. Geef altijd key op voor item in LazyColumn, LazyGrid en andere luie containers. De sleutel stelt Compose in staat elementen te identificeren bij wijziging van de lijst: toevoegen, verwijderen of herschikken. Zonder sleutel herstart Compose alle elementen van de lijst bij elke wijziging, wat op grote lijsten merkbaar prestatieverlies geeft.
// Geoptimaliseerde structuur: stabiele delen apart uitgehaald
@Composable
fun OptimizedScreen(items: List<Item>) {
Column {
Header() // hangt niet af van items — geen hercompositie
Spacer(modifier = Modifier.height(8.dp))
LazyColumn {
items(items, key = { it.id }) { item ->
ItemRow(item = item) // hercompositie alleen voor gewijzigde items
}
}
}
}
@Composable
fun Header() {
Text("Itemlijst", style = MaterialTheme.typography.headlineMedium)
}
@Composable
fun ItemRow(item: Item) {
Text(item.title)
}
Skipping is een mechanisme waarbij Compose de uitvoering van een Composable-functie overslaat als al zijn parameters niet zijn gewijzigd. Om skipping correct te laten werken, moeten parametertypes stabiel (stable) zijn. De Kotlin-compiler markeert als stabiel: primitieve types (Int, Float, Boolean), String, lambda-functies, evenals klassen waarvan alle velden stabiel en val zijn.
Stability is een annotatie @Stable of @Immutable die kan worden toegevoegd aan aangepaste gegevensklassen. Als een klasse een veranderlijk veld (var) bevat, beschouwt de compiler deze als instabiel en Compose kan functies met zulke parameters niet overslaan. Gebruik voor klassen met var @Stable als u garandeert dat de melding over wijziging via het snapshot-systeem wordt verzonden.
Stability kan worden gecontroleerd via de compiler-vlag -P "plugin:androidx.compose.compiler.plugins.kotlin:reportsDestination=. /reports". Het genereert een rapport met een lijst van alle Composable-functies en hun parameters met stabiliteitsaanduiding. Als een parameter instabiel is — is skipping voor die functie onmogelijk en wordt deze bij elke hercompositie van de ouder herstart.
| Type | Stabiliteit | Skipping |
|---|---|---|
| Int, Float, Boolean | Stabiel | Ja |
| String | Stabiel | Ja |
| Lambda | Stabiel | Ja |
| data class met val-velden | Stabiel | Ja |
| data class met var-velden | Instabiel | Nee |
| List<String> | Instabiel | Nee |
Let op: List<String> wordt als instabiel beschouwd omdat dit een interface is, geen concrete implementatie. Gebruik immutableListOf() uit de Kotlin Collections Immutable-bibliotheek of wikkel de lijst in een @Stable-klasse. Lambda is altijd stabiel, omdat zijn equals alleen referenties vergelijkt, en bij het maken van een nieuwe lambda op de aanroeplocatie wordt de bovenliggende functie ook herstart.
Voor monitoring van hercomposities biedt Android Studio Layout Inspector met de modus Compose Recomposition Counts. In deze modus geeft elke Composable-functie het aantal hercomposities en redenen van herstart weer. Dit maakt het mogelijk snel functies te vinden die te vaak worden gehercomponenteerd en de hoofdoorzaak te bepalen — instabiele parameters of overbodige State-afhankelijkheden.
Aanvullende hulpmiddelen: Compose Metrics (verzamelen van statistieken via instrumentation-tests) en Recomposition Timer (meten van uitvoeringstijd van elke functie). Google beveelt aan deze hulpmiddelen in te schakelen in de profileringsfase en uit te schakelen in release-versies, omdat ze tot 20% overhead toevoegen aan elke hercompositie.
Bij analyse van hercomposities zoekt u naar patronen van unnecessary recomposition: een functie wordt herstart hoewel de uitvoer-UI niet zou moeten veranderen. Een veelvoorkomende oorzaak is het gebruik van lambda's zonder remember, waarbij elke keer een nieuw lambda-object wordt gemaakt en Compose de parameter als gewijzigd beschouwt. Oplossing: lambda's in remember { } wikkelen met vaste captures.
// Slecht: nieuwe lambda bij elke hercompositie van ouder
@Composable
fun Parent() {
Child(onClick = { doSomething() }) // elke keer nieuwe lambda
}
// Goed: remember stabiliseert de lambda
@Composable
fun Parent() {
val onClick = remember { { doSomething() } }
Child(onClick = onClick) // zelfde referentie
}
Veelgestelde vragen
Nee, hercompositie is alleen de Composition-fase. Daarna worden Layout en Drawing uitgevoerd. Als na hercompositie de afmetingen en positie van elementen niet zijn gewijzigd, kunnen Layout en Drawing volledig worden overgeslagen, wat GPU-bronnen bespaart.
Bij animaties kan hercompositie tot 120 keer per seconde worden gestart (120fps). Voor normale interactie — 10–60 keer per seconde. Het is belangrijk dat elke hercompositie binnen het framebudget valt (8–16 ms), anders zal de applicatie vertragen.
Oorzaak — wijziging van parameter van de bovenliggende functie. De ouder wordt herstart (om eigen reden) en geeft een nieuwe waarde door. Om dit te voorkomen, controleert u de stability van parameters en gebruikt u remember voor stabilisatie van lambda's en berekende waarden.
Direct uitschakelen is niet mogelijk, maar er is gedwongen skipping via readInComposition — State wordt buiten het functielichaam gelezen, wat geen afhankelijkheid registreert. Gebruik dit voorzichtig: de functie zal niet reageren op wijzigingen, wat kan leiden tot verouderde UI.
Composition is duurder omdat het alle slots en knooppunten van de boom vanaf nul creëert. Recomposition hergebruikt bestaande slots en werkt alleen hun waarden bij. In de praktijk duurt Composition van een scherm 2–10 ms en hercompositie van één element 0.1–1 ms.
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