Diagnose Compose recomposition issues and explain lambda stability

Tests Compose skipping and stability. Strong answers name recomposition counts, compiler metrics, and immutable state, then explain unremembered lambdas create new instances and prevent skipping.
WHAT THIS TESTS: This question probes whether you understand the difference between Compose running and Compose skipping work. At the senior level, the interviewer wants to see that you treat recomposition as a function of input stability, not just state usage. They are looking for systematic debugging habits and precise vocabulary around stability contracts.
A GOOD ANSWER COVERS: First, tooling. Name Android Studio Layout Inspector with recomposition counts and highlighting to visualize which composables restart. Name Compose Compiler metrics, which reports unstable classes and skippable functions in build output. Mention adding SideEffect blocks with logging as a surgical confirmation. Second, explain recomposition skipping. Compose skips a composable only when all parameter types are stable and none have changed since the last frame. If a parameter is an unstable class with mutable fields, Compose conservatively recomposes. Third, explain lambda stability. A lambda that captures variables is instantiated fresh on every recomposition unless it is remembered or replaced with a method reference. A new lambda instance is an unstable changed parameter, so Compose reruns the child even if the lambda body is identical. Fourth, strategies. Audit data models for var properties and non-stable collections like ArrayList; replace them with immutable lists and val properties, or annotate with Stable or Immutable if the contract is correct. Break large screens into smaller stateless composables so skipping granularity is finer. Use remember with keys for derived values and lambdas, but only after the model is stable.
COMMON WRONG ANSWERS: Saying just add remember everywhere without checking why the parent recomposed. Claiming that mutableStateOf causes recomposition instead of reading it. Suggesting derivedStateOf to fix excessive recomposition when the real issue is an unstable data class forcing the parent to restart. Recommending non-skippable wrappers like Box with modifier to somehow block recomposition. Confusing lambda equality by assuming identical source code means identical runtime instance.
LIKELY FOLLOW-UPS: How would you handle a List of unstable items in a LazyColumn? When is it safe to mark a class Immutable versus Stable? How do Kotlin collections like List versus ArrayList affect stability? What changed in recent Compose compiler versions regarding auto-stability for standard collections? How would you verify a fix reduced recompositions in a release build?
ONE CONCRETE EXAMPLE: Suppose a UserProfileScreen recomposes its entire header on every scroll state change. You open Layout Inspector and see the Header composable restarts even though its User parameter is the same object. The Compose Compiler report shows User is unstable because it has a var isOnline field. You refactor User to a data class with all val properties. Now Header becomes skippable. However, the Header still recomposes because it takes an onEdit lambda defined as { viewModel.edit(it) } in the parent. You wrap that lambda in remember(viewModel) { { viewModel.edit(it) } } or pass the viewModel function reference directly. Recompositions drop from dozens per scroll to zero.
Read the original → developer.android.com
- #android
- #jetpack-compose
- #performance
- #recomposition
- #stability
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.