Jetpack Compose is revolutionary, but its "declarative" nature means that a single state change can trigger more work than you intended. If your UI feels laggy during animations or scrolling, you've likely got a recomposition problem.

Unnecessary Recompositions

One common mistake is passing unstable objects (like List from the standard library) into Composables. Because Compose can't guarantee that the list hasn't changed, it recomposes the entire list item even if the data is identical.

The Performance Fix @Composable
fun MyList(items: PersistentList<String>) {
// Use Kotlinx Immutable Collections for better stability
...
}

derivedStateOf to the Rescue

If you have state that depends on other state (like a button being enabled only when a scroll position is past 100), don't calculate it directly in the Composable. Use derivedStateOf to ensure recomposition only triggers when the result of the calculation changes.

Efficient State Dependency val showButton by remember {
derivedStateOf { listState.firstVisibleItemIndex > 0 }
}

The Golden Rule

Always use the Layout Inspector in Android Studio to track recomposition counts. If you see a number incrementing rapidly while the UI is static, you have a state leak that needs fixing. Small optimizations here lead to 60 FPS bliss.

Summary

Stability and derived state are your best friends in Compose. Master the Layout Inspector and keep your recompositions under control!