Hi everyone! I'm using compose navigation 2.8.0 an...
# compose
a
Hi everyone! I'm using compose navigation 2.8.0 and with multiple navigation graphs. Is there a way to pass arguments on a graph level? More in 🧵
My use case is something like this. I have a minigame graph, where every game has its own viewmodel. And there's a common one too, that handles the data savings.
Copy code
navigation<GameGraph>(Game1) {
    composable<Game1> {...}
    composable<Game2> {...}
    composable<Game3> {...}
}
I want to pass a "game mode" argument when navigating to any game that would be handled by the common viewmodel. Is there a way to achieve this?
j
you need do some dependence injection
a
Do you mean accessing the common viewmodel before navigating and passing the argument directly?
s
The graph destination can take in a parameter just as easily as your destination itself can
a
Really, and how do I call navigate on the navcontroller with this method?
s
You call
navController.navigate(SomeGraphDestination(argsHere))
it shouldn't be any different
a
And if I want to navigate directly to Game2 from outside the graph?
s
Then in the composables that are under that graph, you can do
Copy code
val graphRoute = remember(navController, backStackEntry) {
 navController.getBackStackEntry<GameGraph>().toRoute<GameGraph>()
 navController.getBackStackEntry<GameGraph>().toRoute<GameGraph>()
}
I think something like that, I am on a computer right now.
You probably won't be able to navigate directly to Game2, that's true. But if you did that, how would you expect to get the right args in there?
In general, I would most likely not try to do this on the nav level, just store that information on your data layer, since it looks like it transcends any concept of navigation if you want to navigate to individual games anyway. Just shove the information in a DataStore and access that store from anywhere you need to in the app.
a
But if you did that, how would you expect to get the right args in there?
The games each have a callback when saving results which the common viewmoel executes. And the passed argument would determine how to save it.
s
Yeah don't see how it would make sense to store this data as nav args then
a
Just shove the information in a DataStore and access that store from anywhere you need to in the app.
Yeah, this would've been my second attempt.
s
You can make a graph-scoped ViewModel, and put your information in there or course, if you do not want the data to persist to disk, but that's again another thing, you again wouldn't add the args to your GameGraph destination. That would also automatically clear this data when you left the entire graph. However it would not persist across process death etc if you just store it in the ViewModel as a field without SavedStateHandle. DataStore again feels like what you want here tbh
a
Yeah, you're right, thanks for the help ❤️
s
No problem, hope it goes well! ☺️
p
WRT navigate directly to game 2 instead of the initial route. You can check on stackoverflow, there are more than a dozen of questions related to this use case. What I do, far from perfect but not terrible. My initial destination is basically a "route selector". The logic in this destination is just to parse the input arguments and navigate to the desired destination. Visually is ok, it doesn't create any glitch or blink, happens so fast that is unnoticed to the human eye. However, code wise doesn't feel great. I wish it could be part of the NavGraph API itself, let's say if it had a function to override like:
fun onSelectInitialDestination(arg): Destination
Or a setter like
setInitialDestinationSelector(InitialDestinationSelectorInterface)
s
Or... Just navigate to Game2 directly? Definitely don't add "route selector" destinations that also trigger another navigation when you go there, that will just look janky.
p
I thought that initially but if the logic is fast enough it is unnoticed. If the selector logic is heavier and requires a network request. Then a loader could help.
s
Yeah, but you can just navigate to Game2 directly without any of this needed
p
Humm, 🤔 I might be wrong here but, can I navigate to a destination inside a subgraph? Or one can just navigate to the subgraph initial destination? Anyway, I normally try to design my navigation logic in a way that the external callers don't know the inner destinations of the subgraphs. But in any case, I didn't know it was possible to navigate to them, the inner destinations, if you know the route.
s
You can navigate anywhere yes. If it doesn't make sense to navigate to sub-route then you wouldn't expose it in the first place, indeed. If you can navigate there, then you'd want to expose it in a way that you can navigate to it from other modules
p
I see, I thought you couldn't navigate tbh. I thought you would get the route not define exception but I think that is in a different case.