derivedStateOf – abgeleiteten Zustand berechnen, ohne Recompositions zu verschwenden
Wenn du aus einem sich schnell ändernden State einen selten wechselnden Wert ableitest (z. B. "Nach-oben-Button ab Item 5"), verhindert derivedStateOf, dass dein UI bei jedem Scroll-Pixel neu zeichnet.
Ein klassischer Compose-Performance-Fehler: Du liest einen State, der sich sehr oft ändert, um daraus einen Wert zu berechnen, der sich selten ändert. Beispiel: „Zeige den Nach-oben-Button, sobald der Nutzer über Item 5 hinausgescrollt hat." Naiv geschrieben zeichnet dein UI bei *jedem* Scroll-Frame neu – obwohl sich das Ergebnis fast nie ändert.
Das Problem
val listState = rememberLazyListState()
// ❌ liest firstVisibleItemIndex direkt → recomposed bei JEDEM Scroll-Tick
val showButton = listState.firstVisibleItemIndex > 5Jede Scroll-Bewegung ändert firstVisibleItemIndex, also wird der umgebende Composable ständig neu ausgewertet – auch wenn showButton konstant true bleibt.
Die Lösung: derivedStateOf
val showButton by remember {
derivedStateOf { listState.firstVisibleItemIndex > 5 }
}derivedStateOf merkt sich das Ergebnis und benachrichtigt Leser nur dann, wenn sich genau dieses Ergebnis (true/false) ändert – nicht bei jeder Änderung der Eingabe. Aus „recomposed bei jedem Pixel" wird „recomposed genau zweimal": beim Überschreiten und beim Zurückscrollen.
if (showButton) {
FloatingActionButton(onClick = { /* nach oben scrollen */ }) {
Icon(Icons.Default.KeyboardArrowUp, contentDescription = "Nach oben")
}
}Wann – und wann nicht
- Einsetzen, wenn aus einem häufig wechselnden State ein selten wechselnder Wert entsteht (Scroll-Position → Sichtbarkeit, langer Text → „ist gültig").
- Nicht nötig, wenn sich Eingabe und Ergebnis ähnlich oft ändern – dann ist es nur zusätzlicher Overhead. Für eine reine 1:1-Transformation reicht normales
remember(key). - Immer in
rememberwickeln, damit das abgeleitete State-Objekt über Recompositions erhalten bleibt.
Ein flüssiges Scroll-Erlebnis entscheidet oft über den ersten Eindruck einer App. Du willst genau das? Melde dich.
Quellen
Du brauchst mehr als ein Snippet?
Ich entwickle Android-Apps in Kotlin und moderne Websites für Selbstständige und kleine Unternehmen — von der ersten Idee bis zum Release.
Projekt anfragen →Verwandte Snippets
remember vs. rememberSaveable – Zustand, der die Drehung übersteht
remember hält Zustand über Recompositions, verliert ihn aber bei Konfigurationsänderungen wie der Bildschirmdrehung. rememberSaveable rettet einfache Werte automatisch über den Bundle-Mechanismus.
collectAsStateWithLifecycle – Flows sammeln, ohne im Hintergrund zu verschwenden
collectAsState sammelt einen Flow auch, wenn die App im Hintergrund ist. collectAsStateWithLifecycle stoppt automatisch, sobald der Screen nicht mehr sichtbar ist – der richtige Standard für UI-State aus dem ViewModel.
Modifier-Reihenfolge in Compose – warum padding vor background alles ändert
In Jetpack Compose ist die Reihenfolge der Modifier keine Kosmetik, sondern Logik. background vor padding färbt auch den Rand ein, padding vor background nicht. Ein Beispiel, das den Groschen fallen lässt.