https://kotlinlang.org logo
Title
f

Filip Wiesner

01/26/2022, 7:50 PM
Another snapshot question: When I have snapshot inside snapshot (nested snapshot) and I change some state twice inside the inner snapshot and apply, shouldn't the outer snapshot see only one write? I am seeing the write observer being triggered twice 🤔 Code in a thread :thread-please:
val writeObserver: (Any) -> Unit = { writtenState ->
    val s = writtenState as MutableState<String>
    println("State was changed to ${s.value}")
}


var state by mutableStateOf("")

val snap = Snapshot.takeMutableSnapshot(writeObserver = writeObserver)
snap.enter {
    state = "A"
    Snapshot.withMutableSnapshot {
        state = "B"
        state = "C"
    }
}

snap.apply()
snap.dispose()

//The Result is:
//  State was changed to A
//  State was changed to B
//  State was changed to C
The documentation (of
takeNestedMutableSnapshot
which is called by
takeMutableSnapshot
) clearly states that this shouldn't be the case:
Take a mutable snapshot of the state values in this snapshot. Entering this snapshot by calling enter allows state objects to be modified that are not visible to the this, the parent snapshot, until the apply is called.
What am I missing?
Ok, this works:
val snap = Snapshot.takeMutableSnapshot()
snap.enter {
    Snapshot.observe(writeObserver = writeObserver) {
        state = "A"

        val nestedSnap = snap.takeNestedMutableSnapshot()
        nestedSnap.enter {
            state = "B"
            state = "C"
        }
        nestedSnap.apply()
        nestedSnap.dispose()
    }
}
snap.apply()
snap.dispose()

//The Result is:
//  State was changed to A
But frankly I have no idea why. And it also doesn't work like I thought it will. It observes only the "A" change but not the "C" change which kinda makes sense.
Maybe the
currentSnapshot()
function returns the global snapshot and not the
snap
like I thought it will. So when I create snapshot inside another, they are both in GlobalSnapshot. But even then it doesn't make sense to me 😞
@Adam Powell I am really sorry for the ping but I am out of ideas. What am I getting wrong?
a

Adam Powell

02/02/2022, 4:49 PM
I would need to sit down and read this more closely than I can at the moment, @Chuck Jazdzewski [G] might get to it before I do
c

Chuck Jazdzewski [G]

02/02/2022, 5:11 PM
The write observer is not an apply observer. The read and write observers observe all reads and writes, respectively, at the time they are performed and parent snapshots observe all reads and writes of the child snapshots at the time they are performed. The intent of write observers is to notify the observe when a change might be arriving, such as the
GlobalSnapshotManager
does, so it can schedule some action. It is not intended to be used as apply observer which will only send a notification at most once for each change.
objects to be modified that are not visible to the this, the parent snapshot, until the apply is called.
This is referring to the values of the objects not the notification sent to the read and write observers. Changing the value of
state
in
nestedSnap
is not visible in
snap
until
nestedSnap
is applied.