Hey <@UD17D4K8W> (and everyone), Another question...
# ballast
s
Hey @Casey Brooks (and everyone), Another question in terms of nested navigation. From the reading I’ve done regarding the previous questions it seems the preferred solution is to avoid nested routers which I agree with. The only thing I’m wondering is how this paradigm can best align with Compose. E.g.:
Copy code
// ... when (screen) { ... 

AppScreen.Account,
AppScreen.AccountViewProfile -> {
  val vm = remember { AccountScreenViewModel(scope) }
  val state by vm.observeStates().collectAsState()
  when (screen) {
    AppScreen.Account -> AccountScreen(state) { vm.trySend(it) }
    AppScreen.AccountViewProfile -> AccountViewProfileScreen(state)
    else -> throw IllegalStateException("Can't have a different screen here for Account")
  }
}
In this example I have a screen called
Account
with a nested screen which shows more of the profile in details. The problem is that I would like to persist (the state of) the ViewModel but as the recomposition happens, Compose creates a new instance of the ViewModel and the state gets cleared. So there are several ways to approach this issue that I thought of: • Create a nested navigation where
Appscreen.Account
is the main entry point and has several
AccountScreen.xxx
destinations with its own router (did a similar thing for
Login
) • Persist the state and recreate when
Account(ViewProfile)
is opened • Move
AccountViewModel
outside of recomposition space (will live in memory with app lifecycle so not ideal) Is there a better approach I’m missing? I’ve also considered the option of using Ballast Sync, but I’ll basically have the same issues here as the Source (
AccountViewModel
) will still be recreated with navigation.
c
If you start with the assumption that each screen is fully independent of any other and can be accessed purely by visiting a path, then it becomes self-evident that state cannot be directly shared between screens. But state, necessarily, does need to be shared between screens, so the limitation forces you to move the shared state to a different location that can be accessed by both screens. This makes that shared state more robust and testable, since it must be unrelated to the UI or navigation state; it’s just data that lives or is cached somewhere within the application. To that point, your 3rd suggestion is basically what I would recommend, except that you shoudln’t use a ViewModel to hold the state. Move the state into an
AccountRepository
singleton, for example, then both screens can access the data from that Repository. And when building each screen, don’t consider the
AppScreen.Account
to be a screen with sub-screens for
AppScreen.AccountViewProfile
, make the header bit a reusable component that is included in both screens.
👍 1
👍🏾 1