min
06/13/2026, 8:52 AMobject GlobalSnapshotManager advances the global snapshot in a suspending loop on resume if there’ve been writes.
2. a Recomposer invalidates and recomposes its compositions on global snapshot advance.
a. It forwards all changed state objects to every composition.
b. A composition invalidates itself in the context and recompose scopes in it if outdated.
c. The Recomposer recomposes all invalidated compositions, which in turn recomposes all its invalidated scopes
What happens when I write to a state object that a subcomposition has read though? Does the parent composition invalidate the recompose scope (in step 2b) that its context is in? Does recomposing that scope (in step 2c) notify the context to recompose its compositions?min
06/13/2026, 9:54 AM// class LinkComposer.CompositionContextImpl
// - LinkComposer.parentContext: CompositionContext
// - LinkComposer.composition: CompositionImpl
override fun invalidate(composition: ControlledComposition) {
parentContext.invalidate(this@LinkComposer.composition)
parentContext.invalidate(composition)
}
It looks like a CompositionContextImpl (with which subcompositions are to be registered) invalidates
• The composition: ControlledComposition (subcomposition) argument,
• As well as the (super) composition that this: CompositionContextImpl is remembered in,
Both in the context of the super composition, ie recursively upwards until the root Recomposer is reached. So in step 2c, the Recomposer seems to recompose all invalidated toplevel compositions and subcompositions. But how does step 2a forward applied state object changes to subcompositions?min
06/13/2026, 10:05 AMRecomposer.composing composes (one cannot help but notice how every description of Compose sounds like ‘_ship-shipping ship shipping shipping ships_’) its compositions in a snapshot, all recompose scopes that read state objects, whether they’re in one of the toplevel compositions or any of their subcompositions, are recorded in the toplevel compositions. When the toplevel compositions invalidate themselves in step 2b, the necessary subcompositions will be reported to the Recomposer as well. Please let me know if any of this understanding is incorrect!min
06/13/2026, 10:29 AM// class CompositionImpl
override fun recordReadOf(value: Any) {
if (!areChildrenComposing) {
// ...
}
}
No, that cannot be correct. A composition doesn’t map state objects to recompose scopes of its subcompositions that read them.min
06/13/2026, 10:52 AM// class {Composer}.CompositionContextImpl
override fun composeInitial(
composition: ControlledComposition,
content: @Composable () -> Unit,
) {
parentContext.composeInitial(composition, content)
}
• A (parent) Composition can construct and remember a CompositionContext in it.
• A (child) Composition (‘subcomposition’) in the nested context is also composed by the context of the parent composition.
• As a result, a Recomposer: CompositionContext knows its compositions and recursively all subcompositions under them.
• On global snapshot recompose, a Recomposer asks all compositions it knows to invalidate themselves if outdated and recomposes all invalidated ones.
• In the case of a child Composition, it notifies its (nested) context and that of the parent also, which is what recursively propagates invalidation reports eventually to the root Recomposer.