Hello Compose enthusiasts :slightly_smiling_face: ...
# compose
s
Hello Compose enthusiasts 🙂 If I have something like this (in a
ViewModel
for example)
Copy code
private val _selected = mutableStateOf(false)

val isSelected: Boolean
    get() = _selected.value
and use
isSelected
in a composable, it gets recomposed when
_selected
changes although
isSelected
is a
Boolean
and not
State<Boolean>
. How does it work? What is the Compose compiler “magic” here? I would like to understand what’s going on.
I have seen this pattern in state classes of Compose UI for example.
s
Compose doesn't use compiler magic for states, it records the state as "read" whenever
.value
is executed.
Practically, the state system has a global
Snapshot
variable with a
readObserver
field on it. Whenever you call
State.value
, it calls that observer provided by composition.
gratitude thank you 2
s
And when a state is read the next restartable composable in this scope is registered to be recomposed when that state changes?
z
Every time a restartable composable is recomposed, it’s ran with a listener to learn what states are read when the composable function is run. Those state objects are associated with that composable. There’s a global listener for state writes (and applied snapshots) that triggers a new frame when something is written. Then on that frame, we use the set of changed states to figure out which composables need rerunning, and repeat the process.
gratitude thank you 2
This listener mechanism is the simplest part of snapshots actually. Every state object read/write literally just looks at a thread local to find the current snapshot, then calls the read/write listener stored with that snapshot. When you create a snapshot, you have the option of specifying read and/or write observers.
just threadlocals and callbacks
s
Thanks @shikasd and @Zach Klippenstein (he/him) [MOD] for the explanation. I always thought that there is an explicit dependency between a
State
and a composable, meaning it needs to be a
State
(on the first layer) when reading from a composable. I wasn’t aware that there is an implicit dependency which works even when reading a
State
through a layer of abstractions.
This and the succeeding article by Zach about states and snapshots really helped me in better understanding the concepts 🤯 Thanks!