ubuntudroid
11/02/2023, 12:33 PMRouterContract.Events.BackstackChanged
would also pass the old backstack or inform about what exactly has changed. This would enable us to do things like
saveableStateHolder.removeState(it.originalDestinationUrl)
Because right now it doesn’t look like the router manages saveable state for us, right?
So I did something like this:
routerState.renderCurrentDestination(
route = { screen ->
val saveableStateProviderKey = remember(key1 = screen) {
routerState.currentDestinationOrNotFound!!.originalDestinationUrl // seems to be the only way to get hold of the original destination URL
}
saveableStateHolder.SaveableStateProvider(key = saveableStateProviderKey) {
when(screen) {
Screen.Pastes -> {
...
}
Screen.Login -> {
...
}
}
}
},
notFound = {
...
}
)
Casey Brooks
11/02/2023, 3:13 PMrouter.trySend(GoToDestination("/newRoute", NavigationDirection.Forward))
(which is cumbersome and adds extra boilerplate)
3. just ask the user to figure this out for themselves.
#3 is the option I’ve opted for thus far. And to that point, if you need to compare the previous vs current backstacks on each change, it’s not difficult for you to do that yourself. An earlier version actually did include both the previous and current backstacks in the BackstackChanged
event, but ultimately decided that it wasn’t all that useful on its own and pulled it out.BackstackChanged
event comes in, you can simply store the backstack as a variable in the EventHandler class. Events are processed sequentially so you will never need to worry about race conditions or anything like that, though it is running asynchronous with respect to the UI. So you might need to handle that kind of “clearing” logic from somewhere within the Compose UI, rather than the EventHandler.ubuntudroid
11/02/2023, 3:47 PMCasey Brooks
11/02/2023, 4:10 PMfun <T: Any> Flow<T>.zipWithNext(): Flow<Pair<T?, T>> = flow {
var prev: T? = null
collect { value ->
emit(prev to value)
prev = value
}
}
val zippedFlow: Flow<Pair<Backstack<Screen>?, Backstack<Screen>>> = remember(router) {
router.observeStates().zipWithNext()
}
val value: Pair<Backstack<Screen>?, Backstack<Screen>>? by zippedFlow.collectAsState(initial = null)
if(value != null) {
val (oldBackstack, currentBackstack) = value!!
currentBackstack.renderCurrentDestination(
route = { screen ->
LaunchedEffect(key1 = screen) {
// clear the values from the old backstack
}
when(screen) {
Screen.Pastes -> {
PastesScreen.Content(router)
}
Screen.Login -> {
LoginScreen.Content(router)
}
}
},
notFound = {
// TODO add "not found" screen
}
)
}
ubuntudroid
11/02/2023, 4:40 PM