min
09/01/2025, 11:55 AM@Composable to inject an output parameter of sorts at compile time via which composables build a composition. I suppose that ‘recomposition scopes’ emitted into the composer by composables somehow correspond to snapshots, and that once a recomposition scope has been invalidated because a state has changed, a rerun of the corresponding composable is scheduled. But where is the code that actually does this? My MainActivity is a ComponentActivity, I’ve had a quick look at the call graph that starts from the call to .setContent in the onCreate method but couldn’t identify whatever is orchestrating this chain of eventsChrimaeon
09/01/2025, 1:12 PMmin
09/02/2025, 5:48 AMval state = mutableIntStateOf(42)
var nReads = 0
var nWrites = 0
Snapshot.observe(
readObserver = { target: Any -> Unit; if (target == state) nReads += 1 },
writeObserver = { target: Any -> Unit; if (target == state) nWrites += 1 },
) {
kotlin.test.assertEquals(42, state.value)
state.value = 16
state.value = 78
}
kotlin.test.assertEquals(78, state.value)
kotlin.test.assertEquals(1, nReads)
kotlin.test.assertEquals(2, nWrites)
Where in Compose does it install an actual read/write observer like this?min
09/02/2025, 6:05 AMcomposer.currentRecomposeScope?.let {
it.used = true
val alreadyRead = it.recordRead(value)
if (!alreadyRead) {
if (value is StateObjectImpl) {
value.recordReadIn(ReaderKind.Composition)
}
observations.add(value, it)
This in internal class CompositionImpl I feel is the closest I’ve got to the answer. I suppose that nothing happens automatically and each implementation of Composition should take care to record what states an instance of it has read (e.g. value) and which scopes are invalidated (e.g. it) when the recorded states have changed. But this just explains what keeps track of which recomposition scopes to invalidate on state changes (each composition does), I still don’t know what actually observes reads and writesAlbert Chang
09/03/2025, 9:52 AMmin
09/03/2025, 10:45 AMComponentActivity::onCreate calls this.setContent(parent: CompositionContext? = null, content: @Composable () -> Unit). The method (essentially) gets hold of existingComposeView ?: ComposeView(this) and calls .setParentCompositionContext(parent: CompositionContext?), and .setContent(content: @Composable () -> Unit). As a result of the latter, (AbstractComposeView::createComposition)(this) is called. Would you be so kind as to point out which of these leads to the functions you’ve linked to, please? I’m completely new to Android and I still find that the Jetpack codebase rather expansive. The composing function you’ve linked seems to be the culprit I’ve been looking for (massive thanks for telling me), I can’t seem to identify which chain of calls leads to it 😭Albert Chang
09/03/2025, 10:52 AM