What is the composition lifecycle?
Understand when Compose starts keeping a part of the UI, what recomposition means while it remains there, and what happens when that part leaves.
What the interviewer is testing
The interviewer is testing whether you can separate recomposition from lifetime.
A composable function may run many times while Compose is still keeping the same part of the UI. The important question is not simply how many times the function ran, but whether that part of the UI is still in the Composition or has actually left it.
That distinction is what lets you reason correctly about remembered state, effects, and cleanup.
❌ Common mistake
If they ask you to elaborate
Start with the mental model from composition:
Composition is the UI that Compose remembers between executions of your composable functions.
The lifecycle question is the next step:
How long does Compose keep a particular part of that UI?
Imagine a checkout screen:
@Composable
fun CheckoutScreen(
showSummary: Boolean
) {
CheckoutForm()
if (showSummary) {
OrderSummary()
}
}Suppose the screen first runs with:
showSummary = falseThe UI Compose is keeping can be pictured like this:
CheckoutScreen
└── CheckoutFormOrderSummary is not part of the UI yet.
Later:
showSummary = trueCheckoutScreen() runs again. This time the condition calls OrderSummary().
Now you can picture the Composition like this:
CheckoutScreen
├── CheckoutForm
└── OrderSummaryCompose is now keeping track of OrderSummary as part of the current UI.
That is what it means for OrderSummary to enter the Composition.
Nothing is physically entering a container somewhere. It simply means that this part of the UI is now part of what Compose is remembering and managing.
So what is Compose actually remembering?
It is worth looking just slightly beneath the mental model, because otherwise this can feel like magic.
Compose is not remembering a screenshot, and it is not storing the finished result of OrderSummary().
As composable functions run, Compose keeps internal bookkeeping about the composable calls that make up the current Composition. During recomposition, the runtime uses that information to update the Composition and determine which parts are still present and which are no longer being produced.
The runtime goes much deeper than that, but you do not need its internal data structures to understand the lifecycle.
For this page, the useful picture is simply:
your composable functions run
↓
Compose keeps track of the UI they describe
↓
that remembered UI is the CompositionNow suppose OrderSummary reads some state:
@Composable
fun OrderSummary(
total: Money
) {
Text("Total: $total")
}The total changes.
Compose may run OrderSummary() again so the text can be updated.
That is recomposition.
But look at what happened to its lifecycle:
OrderSummary enters
↓
Compose keeps it
↓
total changes
↓
OrderSummary recomposes
↓
Compose is still keeping itIt did not leave just because its function ran again.
It may recompose many times while it remains part of the Composition. Compose may also skip running it during an update when there is nothing there that needs changing.
Either way, it can still be part of the Composition.
Now the user goes back to editing the checkout and:
showSummary = falseThe condition no longer calls OrderSummary().
The UI is back to:
CheckoutScreen
└── CheckoutFormCompose no longer needs to keep OrderSummary as part of this Composition.
Now it has left the Composition.
So the lifecycle is easier to picture as:
Compose starts keeping this part of the UI
↓
ENTER
↓
it may recompose 0..n times
↓
Compose is still keeping it
↓
Compose stops keeping this part of the UI
↓
LEAVEThat is the distinction to hold onto.
Recomposition is something that can happen during the lifetime.
Leaving the Composition is what ends that lifetime.
Why does that matter for remember?
Now the behaviour of remember becomes much easier to reason about:
@Composable
fun OrderSummary() {
var expanded by remember {
mutableStateOf(false)
}
// ...
}When OrderSummary enters the Composition, Compose can keep that remembered value with its place in the Composition.
If OrderSummary recomposes, Compose is still keeping that part of the UI, so the remembered value can be reused.
OrderSummary enters
↓
expanded is remembered
↓
recomposition
↓
same remembered value
↓
recomposition
↓
same remembered valueWhen OrderSummary actually leaves the Composition, that remembered state no longer belongs to an active part of this Composition.
If OrderSummary appears again later, that is a new Composition lifetime and plain remember should not be treated as though the previous one never ended.
This is why understanding the lifecycle is more useful than counting how many times a composable function executes.
Production thinking
Imagine you are building a shopping app and the checkout can show an optional promo-code section:
@Composable
fun CheckoutScreen(
hasPromoCode: Boolean
) {
CheckoutForm()
if (hasPromoCode) {
PromoCodeSection()
}
}Inside that section, the user can expand some help text:
@Composable
fun PromoCodeSection() {
var showHelp by remember {
mutableStateOf(false)
}
// ...
}Now walk through what happens in the real screen.
The user adds a promo code.
hasPromoCode = truePromoCodeSection enters the Composition and showHelp starts as false.
The user opens the help text:
showHelp = trueThat state change can cause recomposition.
Maybe the cart total also changes afterward and the checkout recomposes again.
None of those updates mean the promo section disappeared.
Compose is still keeping that part of the UI, so its remembered showHelp state stays with it.
promo section appears
↓
showHelp = false
↓
user opens help
↓
showHelp = true
↓
checkout updates
↓
promo section recomposes
↓
showHelp is still trueNow the user removes the promo code.
hasPromoCode = falseThis is different.
PromoCodeSection() is no longer called, so Compose stops keeping that part of the UI.
The promo section has left the Composition.
Its plain remember state belonged to that place in the Composition, so when the section is removed, that remembered value is forgotten.
If the user adds a promo code again later, the section enters again:
promo section enters
↓
showHelp = falseThat is often exactly what you want for temporary UI state.
But now imagine the product requirement changes:
"If the promo section disappears and comes back, restore whether the help was open."
That requirement is telling you something important.
The state now needs to survive longer than this particular Composition lifetime.
At that point, plain remember is no longer enough. You would choose an owner or state-saving mechanism whose lifetime matches the behaviour you actually need.
The same reasoning applies to effects.
If some work should exist only while PromoCodeSection is part of the Composition, its lifetime can naturally follow that UI.
If the work must continue after the promo section disappears, then that composable is too short-lived to own it.
That is the production value of understanding the composition lifecycle.
You stop asking:
"Which Compose API should I use?"
and start with:
"How long should this state or work live?"
Then you compare that requirement with the lifetime of the UI:
Should it live only while this UI is present?
↓
Composition lifetime may be the right owner
Should it survive this UI leaving?
↓
It needs a longer-lived owner or saving mechanismThat is the same ownership thinking that makes remember, effects, state holders, and navigation state much easier to reason about.