can someone point me to a good article/documentati...
# compose-desktop
d
can someone point me to a good article/documentation on "what gets redrawn when"? especially on the question "if state changes, how does compose decide what has to be redrawn", thanx (as anything is a function, I wonder on what it is inside the function that compose "remembers" and how he "finds" the function to be reexecuted when ... yeah, when what!?)
👍 1
t
a
When you take a Snapshot you can get a callback whenever something reads a value from that snapshot: https://developer.android.com/reference/kotlin/androidx/compose/runtime/snapshots/Snapshot#Companion.takeSnapshot(kotlin.Function1)
Compose does this while composition is in progress, and compose UI additionally does it while running measure, layout, and drawing.
This is used to build a list of state records that will invalidate the scopes that the reads occurred in
Which is a signal to compose to invalidate any scopes that referenced the objects that changed
d
so if I store my state, let's say in a Singleton ... and function body uses singleton methods to get/set state ... the function will not be marked as to be redrawn, right? Some value of the method's signature(?) has to change (be dependant on the state) for the method contents to be re-executed !?! right?
a
If you write this:
Copy code
object MySingleton {
  private var myPrivateState by mutableStateOf(0)

  fun increment() {
    myPrivateState++
  }

  fun getCurrentMessage() = when {
    myPrivateState == 0 -> "none"
    myPrivateState < 5 -> "a few"
    else -> "a lot"
  }
}
and then in your composable function you write:
Copy code
Text(MySingleton.getCurrentMessage())
then the text will update whenever the singleton's internal state changes.
d
and the reason is the changing method call parameter of
Text(...)
if e.g. the parent method of the
Text(...)
would NOT have the `MySingleton.myPriateState`somewhere as method parameter, the
Text(...)
would still be redrawn on change, but parent method itself not ... have I understood correctly?
or another way to express ... for any method anotated with
@Composable
Compose will remember the values of all its function-parameters and if some will change (and only then), the method is called/executed again with new new values
a
When your composable call ran the first time, compose kept a record that somewhere in the call stack, the
mutableStateOf
in
MySingleton
was read. When it changes, compose will re-execute your composable function, which will call
MySingleton.getCurrentMessage()
again, which will return a new value and record that that snapshot state object was still read during that recomposition.
d
so it is not necessarily to be a direct parameter of that function, but it has to be ... hmmm ... in the stacktrace of the function execution somewhere? so whenever a @Composable function - on first execution - "hits" a (what?
State
?) all(?) methods in that stacktrace that are marked with
@Composable
are "internally" stored in a "`Map<State, Set<Function>>`" ... would that be the right "mental abstraction" ?
a
not just on first execution, on any execution. Compose only remembers the most recent recomposition pass's inputs.
and then this method is called by a snapshot apply observer to invalidate the associated scopes: https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:compose/[…]in/androidx/compose/runtime/Composer.kt;l=1270
measure/layout/draw have similar configurations
compose goes through all of this to avoid adding a ton of individual snapshot observers all over for general efficiency, but if you want to do your own targeted observation of data derived from a snapshot, you can use the
snapshotFlow {}
flow builder
the resulting flow will emit a value whenever snapshot state inputs inside the given function block change
c
Adam Powell... the GOAT Super helpful answers. Digging into some of this now. 🙏
💯 1