Posts

Why are Function Types Stable in Jetpack Compose?

Image
 Unpacking the "Observability Gap" and why () -> Unit is stable even when its data is not. Why does a lambda that returns unstable data still count as “stable” in Compose? The answer reveals how recomposition actually works under the hood. TL;DR:  In Jetpack Compose, function types (lambdas) are considered  stable  because their  identity  is the only observable signal Compose can use during recomposition. However, stability does not guarantee reactivity — state must be read inside composables, not hidden inside lambdas. To maintain performance, you must manually manage identity using  remember . The Mental Model: Compose Recomposition vs. Execution Phase To understand function stability, you must distinguish between the two distinct timings in a Composable’s lifecycle: Recomposition Phase:  Compose compares inputs to decide if it can skip a function. If inputs (like a lambda) have the same  identity , Compose  skips  the work. E...

Jetpack Compose Under the Hood: The Magic of @ReadOnlyComposable 💡

Image
 Unlocking performance by stripping away Slot Table overhead in high-frequency recomposition paths. If you’ve ever explored the Jetpack Compose source code — perhaps while poking around  MaterialTheme  or  LocalContext —you might have noticed a specific, low-level annotation:  @ReadOnlyComposable . While  @Composable  is the bread and butter of Android development,  @ReadOnlyComposable  is a specialized  micro-optimization tool  used for high-frequency contextual accessors. Let’s unmask how it works at the compiler level and why breaking its contract is so dangerous. What Exactly is  @ReadOnlyComposable ? In standard Compose, most composable calls introduce a  group boundary  in the  Slot Table . This group allows the runtime to track the call site’s identity, manage state, and handle “skipping” logic. @ReadOnlyComposable  changes this fundamental behavior. It tells the compiler: “I need to be a Composable t...