Stardust
08/04/2025, 1:46 PMclass MyStateObject(private var value: Int): StateObject {
private var stateRecord = MyRecord()
override val firstStateRecord: StateRecord
get() = stateRecord
override fun prependStateRecord(value: StateRecord) {
stateRecord = value as MyRecord
}
var intValue: Int
get() {
stateRecord.readable(this)
// Do not read the value from the record, always use the "latest" value
return this@MyStateObject.value
}
set(value) {
stateRecord.writable(this) {
// Instead of writing the value to the specified "current" record, the "latest" value is written
this@MyStateObject.value = value
}
}
// This Record does not actually do anything and does not record anything.
private class MyRecord: StateRecord() {
override fun assign(value: StateRecord) {
}
override fun create(): StateRecord {
return MyRecord()
}
}
}
I'm wondering where in Compose does snapshots or similar functionality use this internally? Will my implementation encounter any real-world issues, such as animations? (My code doesn't use snapshots.)
The reason for this is that I have a very large list of data, and only one copy of it exists in memory. I can't have any copies or snapshots. Whenever I read it, I only get the latest data, and the list is constantly changing. Therefore, I can't use SnapshotStateList.Zach Klippenstein (he/him) [MOD]
08/04/2025, 3:25 PMZach Klippenstein (he/him) [MOD]
08/04/2025, 3:26 PMZach Klippenstein (he/him) [MOD]
08/04/2025, 3:27 PMZach Klippenstein (he/him) [MOD]
08/04/2025, 3:27 PMZach Klippenstein (he/him) [MOD]
08/04/2025, 3:39 PMStardust
08/18/2025, 3:06 AMprivate inline fun <T> composing(
composition: ControlledComposition,
modifiedValues: MutableScatterSet<Any>?,
block: () -> T
): T {
val snapshot = Snapshot.takeMutableSnapshot(
readObserverOf(composition), writeObserverOf(composition, modifiedValues)
)
try {
return snapshot.enter(block)
} finally {
applyAndCheck(snapshot)
}
}
From this code, it seems that if I'm not modifying state multithreaded, theoretically, the behavior of not saving historical snapshots is equivalent to saving snapshots. This is because Recomposer always uses the latest snapshot, applies changes after modification, and throws an exception if the apply fails. In other words, Compose currently doesn't support concurrent (unmergeable) state modifications during the recomposition process.
I'm not sure whether snapshots are used in animations or other scenarios.Zach Klippenstein (he/him) [MOD]
08/18/2025, 3:03 PMthe only place Compose uses snapshots is in the following code in RecomposerThat is perhaps currently true of the compose runtime, but not of compose UI, which also uses them for layout, draw, graphicslayer, etc. And it is not a good idea to rely on specific implementation details over the documented contract because if you do that, when the implementation details inevitably change, your code will break. Fighting a framework will always be a bad time, there are other solutions to your problem that actually do work and also comply with the snapshot contract.