0
0
Android Kotlinmobile~15 mins

Recomposition concept in Android Kotlin - Deep Dive

Choose your learning style9 modes available
Overview - Recomposition concept
What is it?
Recomposition is the process where the user interface updates itself when the data it depends on changes. In Android development with Jetpack Compose, the UI is described by functions that can be re-run to reflect new data. This means the screen redraws only the parts that need to change, making apps efficient and responsive.
Why it matters
Without recomposition, apps would have to redraw the entire screen every time something changes, wasting battery and making the app feel slow. Recomposition helps apps update smoothly and quickly, improving user experience and saving device resources.
Where it fits
Before learning recomposition, you should understand basic Kotlin programming and how Jetpack Compose builds UI with composable functions. After mastering recomposition, you can explore state management, side effects, and performance optimization in Compose apps.
Mental Model
Core Idea
Recomposition is like refreshing only the parts of a painting that have changed, instead of repainting the whole canvas every time.
Think of it like...
Imagine a newspaper where only the weather section updates daily, so the rest of the pages stay the same. Recomposition updates just the changed parts of the UI, not the entire screen.
┌─────────────────────────────┐
│       UI Screen             │
│ ┌───────────────┐           │
│ │ Part A        │           │
│ ├───────────────┤           │
│ │ Part B (data) │ ← Changes │
│ ├───────────────┤           │
│ │ Part C        │           │
│ └───────────────┘           │
└─────────────────────────────┘

Only Part B recomposes and redraws when its data changes.
Build-Up - 7 Steps
1
FoundationWhat is Recomposition in Compose
🤔
Concept: Recomposition means re-running composable functions to update the UI when data changes.
In Jetpack Compose, UI is built with composable functions. When the data these functions use changes, Compose automatically calls them again to update the screen. This process is called recomposition.
Result
The UI updates smoothly to show the latest data without rebuilding everything manually.
Understanding recomposition is key to building dynamic and responsive UIs in Compose.
2
FoundationHow Compose Detects Data Changes
🤔
Concept: Compose tracks state variables to know when to trigger recomposition.
Compose uses special state holders like mutableStateOf to watch data. When this data changes, Compose knows which composables depend on it and recomposes only those parts.
Result
Only UI parts that use changed data are refreshed, saving work and improving performance.
Knowing how Compose tracks state helps you write efficient UI that updates correctly.
3
IntermediateState and Recomposition Relationship
🤔Before reading on: do you think changing any variable triggers recomposition or only special state variables? Commit to your answer.
Concept: Only state variables wrapped in Compose's state holders trigger recomposition when changed.
Regular Kotlin variables do not cause recomposition. You must use Compose state types like mutableStateOf or remember to hold data that should trigger UI updates.
Result
UI updates only when intended, avoiding unnecessary redraws.
Understanding this prevents bugs where UI does not update or updates too often.
4
IntermediateRecomposition Scope and Granularity
🤔Before reading on: do you think recomposition refreshes the whole screen or just parts? Commit to your answer.
Concept: Recomposition happens only for composables that read changed state, not the entire UI tree.
Compose tracks which composables read which state. When state changes, only those composables re-run. This fine-grained control makes UI updates efficient.
Result
Apps feel faster and use less battery because only necessary UI parts update.
Knowing recomposition scope helps you design composables that minimize unnecessary updates.
5
IntermediateRemember and Recomposition Optimization
🤔
Concept: Using remember helps Compose keep values across recompositions and avoid repeating expensive work.
The remember function stores a value during recomposition so it doesn't get recreated every time. This is useful for caching or holding objects that don't change often.
Result
UI updates faster and uses less memory by avoiding repeated calculations.
Using remember wisely improves app performance and user experience.
6
AdvancedSide Effects and Recomposition Control
🤔Before reading on: do you think recomposition can cause side effects like network calls? Commit to your answer.
Concept: Recomposition can re-run code multiple times, so side effects must be managed carefully with effect handlers.
Compose provides side effect APIs like LaunchedEffect and DisposableEffect to run code only when needed, avoiding repeated side effects during recomposition.
Result
Apps behave correctly without unwanted repeated actions during UI updates.
Understanding side effects prevents bugs and performance issues in Compose apps.
7
ExpertRecomposition Internals and Skipping
🤔Before reading on: do you think Compose always re-runs composables on state change or can it skip some? Commit to your answer.
Concept: Compose uses smart algorithms to skip recomposition when inputs haven't changed, improving efficiency.
Compose compares parameters and state reads to decide if recomposition is needed. If nothing changed, it skips re-running the composable, saving CPU and battery.
Result
Highly optimized UI updates that feel instant and smooth even in complex apps.
Knowing how Compose skips recomposition helps you write composables that cooperate with this optimization.
Under the Hood
Jetpack Compose uses a runtime that tracks which composable functions read which pieces of state. When a state changes, Compose schedules recomposition for only those composables. It uses a slot table to store UI state and compares inputs to decide if recomposition can be skipped. This incremental update model avoids redrawing the entire UI tree.
Why designed this way?
Traditional UI frameworks redraw entire screens or views on changes, causing inefficiency. Compose was designed to be declarative and reactive, updating only what changed. This design improves performance, reduces boilerplate, and fits modern app needs for smooth, dynamic interfaces.
┌───────────────┐
│ State Change  │
└──────┬────────┘
       │ triggers
┌──────▼────────┐
│ Compose Runtime│
│ tracks reads  │
│ and schedules │
│ recomposition │
└──────┬────────┘
       │ recomposes
┌──────▼────────┐
│ Composable    │
│ functions run │
│ update UI     │
└───────────────┘
Myth Busters - 4 Common Misconceptions
Quick: does changing any Kotlin variable trigger recomposition? Commit yes or no.
Common Belief:Changing any variable in a composable causes recomposition automatically.
Tap to reveal reality
Reality:Only changes to Compose state variables (like mutableStateOf) trigger recomposition.
Why it matters:Using regular variables for UI data means UI won't update, causing stale or incorrect displays.
Quick: does recomposition mean the whole screen redraws? Commit yes or no.
Common Belief:Recomposition always redraws the entire UI screen.
Tap to reveal reality
Reality:Recomposition only re-runs composables that read changed state, not the whole UI.
Why it matters:Thinking recomposition is expensive may lead to unnecessary optimization or complex code.
Quick: can side effects safely run inside composables during recomposition? Commit yes or no.
Common Belief:You can run side effects like network calls directly inside composables without issues.
Tap to reveal reality
Reality:Side effects must be managed with effect APIs; otherwise, they may run multiple times causing bugs.
Why it matters:Ignoring this causes repeated network calls or resource leaks, harming app stability.
Quick: does Compose always re-run composables on every state change? Commit yes or no.
Common Belief:Compose always re-runs all composables that read state when any state changes.
Tap to reveal reality
Reality:Compose can skip recomposition if inputs haven't changed, optimizing performance.
Why it matters:Not knowing this may lead to overcomplicated code trying to manually prevent recomposition.
Expert Zone
1
Compose's slot table stores UI state efficiently, enabling fast recomposition without rebuilding the entire UI tree.
2
Parameter equality checks during recomposition use smart heuristics, so passing stable data types improves skipping.
3
Recomposition can be triggered by indirect state changes, so understanding state flow is crucial to avoid unexpected UI updates.
When NOT to use
Recomposition is core to Compose and always used for UI updates. However, for very static screens or performance-critical animations, consider using remember or derivedStateOf to minimize recomposition. For legacy Android Views, recomposition does not apply; use View system updates instead.
Production Patterns
In real apps, developers split UI into small composables to limit recomposition scope. They use state hoisting to control data flow and remember to cache expensive calculations. Side effects are handled with LaunchedEffect to avoid repeated actions. Profiling tools help identify unnecessary recompositions for optimization.
Connections
React Virtual DOM
Both use a declarative UI model with efficient updates by comparing previous and current UI states.
Understanding React's Virtual DOM helps grasp how Compose minimizes UI work by recomposing only changed parts.
Functional Programming
Recomposition relies on pure functions (composables) that produce UI from data, similar to functional programming principles.
Knowing functional programming concepts clarifies why composables are designed to be side-effect free and easily recomposable.
Incremental Compilation in Software Build Systems
Both recomposition and incremental compilation avoid redoing work by only updating changed parts.
Seeing recomposition like incremental compilation helps understand the efficiency gains from partial updates.
Common Pitfalls
#1UI does not update when data changes.
Wrong approach:var count = 0 @Composable fun Counter() { Text(text = "Count: $count") } // Later count++
Correct approach:var count by mutableStateOf(0) @Composable fun Counter() { Text(text = "Count: $count") } // Later count++
Root cause:Using regular variables instead of Compose state means Compose doesn't know to recompose.
#2Side effects run multiple times causing repeated network calls.
Wrong approach:@Composable fun LoadData() { // This runs on every recomposition fetchDataFromNetwork() Text("Loading") }
Correct approach:@Composable fun LoadData() { LaunchedEffect(Unit) { fetchDataFromNetwork() } Text("Loading") }
Root cause:Running side effects directly in composables causes them to repeat on every recomposition.
#3Unnecessary recompositions slow down the app.
Wrong approach:@Composable fun Greeting(name: String) { Text("Hello, $name!") } // Called with new String instance each time Greeting(name = "John" + "")
Correct approach:val stableName = remember { "John" } Greeting(name = stableName)
Root cause:Passing new objects or unstable parameters causes Compose to think data changed, triggering recomposition.
Key Takeaways
Recomposition is the process where Jetpack Compose updates only the parts of the UI that depend on changed data.
Compose tracks special state variables to know when to re-run composable functions, making UI updates efficient and smooth.
Using remember and side effect APIs properly helps control recomposition and avoid bugs or performance issues.
Compose's smart skipping of recomposition based on input equality is a powerful optimization to write fast apps.
Understanding recomposition deeply enables building responsive, maintainable, and high-performance Android apps with Compose.