Brifing

Jetpack Compose Performance Issue: Recomposition

The hidden cause of your app's lag and how to fix it

ProAndroidDev - Medium2 min

1What is Recomposition?

In Jetpack Compose, the user interface is rebuilt based on state changes. This process is called recomposition. Ideally, Compose skips unchanged components and only rebuilds the necessary parts. However, using unstable parameters can cause unnecessary recompositions of entire components, leading to performance issues.

2The Stability Problem

Compose checks component stability at compile time. Using mutable collections like MutableList prevents Compose from guaranteeing parameter stability. As a result, components are unnecessarily recomposed during every recomposition. For example, a LazyColumn with 50 items could trigger 50 unnecessary recompositions on each scroll.

3Solution: Immutable Collections

Replacing MutableList with kotlinx.collections.immutable.ImmutableList provides Compose with a guarantee of immutability. This marks components as stable, preventing unnecessary recompositions. This change can significantly improve performance, especially in list-heavy screens.

4Detection with Layout Inspector

Android Studio's Layout Inspector includes a feature to show recomposition counts. This tool helps identify components that are being unnecessarily recomposed. For instance, if a component recomposes hundreds of times after typing three characters, it indicates a stability issue.

5Lambda Pitfalls

Lambda expressions passed as parameters to composable functions can be recreated on every recomposition. This prevents components from being marked as stable. Using the remember function to preserve lambda identity allows Compose to skip unnecessary recompositions.

6Using derivedStateOf

derivedStateOf optimizes derived states. For example, when filtering in a search bar, recomposition can be skipped for state changes that produce the same result. This provides noticeable performance improvements, especially on mid-range devices.

7Narrow State Reading

Using a broad UiState class can tie all components to a single state change. Instead, reading states as narrow flows ensures each component only reacts to the state changes it needs. For example, a header component won't be affected by typing indicator changes.

8The Importance of Optimization

Recomposition optimizations directly impact user experience. Unnecessary recompositions can make the app feel slow and unresponsive. These issues are more noticeable in list-heavy screens and on mid-range devices. Proper optimization techniques can significantly improve your app's performance.

Original article: ProAndroidDev - Medium — Jetpack Compose'da Performans Sorunu: Recomposition