In `nav3` ```val backstack = rememberNavBackstack...
# compose
u
In
nav3
Copy code
val backstack = rememberNavBackstack()
// Bring to top
val index = backstack.indexOf(Foo)
if index > 0
   val foo = backstack.removeAt(index)
   backstack.add(foo)
This seems to work for reordering existing screen to top of backstack - but, doesn’t it technically remove the screen for a split second - possibly triggering disposal callbacks and others? Or is backstack “applied” only at vsync time?
t
changes to
backstack
, assuming it is backed by snapshot state, are "applied" after composition and the new value is visible only to the next composition
That is probably wrong
It is; the value is visible immediately but side effects and recompositions with the new value take place later (essentially next frame)
u
is this guaranteed? i.e. can composition happen between my reset and add somehow?
but regardless, the recomposition, is it smart enough to know its the same identity so don’t run removal sideffects etc?
im reading something about snapshots so idk if they are or not necessary here
t
Today, I believe that is guaranteed behavior, but multi-threaded composition is likely to come in the future. I don't think you will have a problem with this code, or a lot of other things can break. There is an API,
Snapshot.withMutableSnapshot
, that basically guards against other threads seeing the intermediate state before it's all applied.
u
wait what? ui stuff off main thread?
t
Just composition
u
okay but currently, how does it work? you say sideffects are deferred to next composition but is next composition then offset by my code somehow, or completely unrelated? what i means is, if i were to put thread,sleep inbetween the remove and add, could it somehow mess up the desired atomicity and leak into the next composition?
t
If you did that then I believe the first half of the change would not be marked as "applied" and wouldn't trigger recompositions.
Oh but this isn't happening in-composition, it's a callback, so it will block the UI thread unless you choose to do this asynchronously.
u
okay i see so would you rely on the implicit contract or snapshot explicitly?
w
I've been wrapping remove and add with
withMutableSnapshot
anyways because it helps communicate to a reader that a change is transactional and expected to never recompose in the middle. And that way you don't need to worry about what thread it's invoked in.
👆 1
u
shame then thst recipes do clear + add as to set new root and clear evrything okay than yous! all over the place