Yevhenii Nadtochii
01/18/2024, 1:24 PMclass MyState(initialValue: String) {
var value by mutableStateOf(initialValue)
}
If I create an instance of MyState
at some point within the composition and immediately try to update myState.value
from a new coroutine with Dispatchers.Default
, I will get the following exception: Reading a state that was created after the snapshot was taken or in a snapshot that has not yet been applied
.
Usage of Dispatchers.Main
seems to help. Each composable is both a separate snapshot and a coroutine in Dispatchers.Main
? So, scheduling a coroutine on top of Main
is always safe, as the current composition will be committed by the moment the observable value is updated from the launched coroutine.
Is the assumption with Dispatchers.Main
true?Garret Yoder
01/18/2024, 6:06 PMGarret Yoder
01/18/2024, 6:07 PMYevhenii Nadtochii
01/19/2024, 11:04 AMAlso, why do you need to wrap the state value in a class?
MyState
class has several mutableStateOf()
fields. The problem is that it updates them from external events. During the class initialization, it subscribes for some external events and updates observable properties as these events arrive. The events are dispatched from a separate background thread. Thus, they may arrive as soon as an instance is initialized, knowing nothing about the nature of Compose observables.
you can use LaunchedEffect to solve thisIn this case, it is just inconvenient. I could ask for
scope
in the class constructor, stating in docs that the scope from Compose should be passed here. But this is something I would like to avoid, if possible.
But as for now, I don’t see other workable options besides Dispatchers.Main
(on which I should not rely).Garret Yoder
01/19/2024, 3:32 PMYevhenii Nadtochii
01/19/2024, 3:47 PM