I\'m just going to start this off being SUPER honest. I hate navigation
with JC. Why? It\'s just trash. Android devs fought so hard for nav
graph and then to have to revert to manually code the flow again feels
like a big slap in the face.
Anyway it took me quite some time to understand the documentation around
nested navigation so that I could have an auth flow and then my main app
flow. I\'m going to try to break it down here. (Resource at the end)
The Code
--------
I don\'t want this to be super boring and technical so I added comments
to the code and then included a high level breakdown.
Main Activity:
...
@Composable
fun Main(){
val navController = rememberNavController()
NavHost(navController, startDestination = StartupNavigationScreens.Login.route) {
composable(StartupNavigationScreens.Login.route) { Login(navController) }
composable(StartupNavigationScreens.Register.route) { Register(navController) }
mainGraph(navController) //notice no composable but will go to the mainGraph
}
}
...
composable in MainActivity.kt
### Main Breakdown
In your main activity you should have your starter graph. In this case
it\'s my \"authentication graph\". I recommend you start with just a
movement between screen here before breaking out into the next step.
You might be wondering where this `StartupNavigation` class is. Well
it\'s in the `Navigation.kt` code below. I did that to keep
`MainActivity` clean. It\'s a view and as such I want to keep view code
only in there.
I want you to notice that the `mainGraph` isn\'t wrapped in a composable
like the other screens. Why? Well when I initially did it that why the
navigation \"worked\" but there was a blank screen. I\'ll explain where
that code went below.
Navigation:
// Authentication screens
sealed class StartupNavigationScreens(val route: String) {
object Login : StartupNavigationScreens("login")
object Register : StartupNavigationScreens("register")
object Main : StartupNavigationScreens("main")
}
// Main app screens
sealed class MainNavigationScreens(val route: String) {
object Home : MainNavigationScreens("home")
object Secondary : MainNavigationScreens("second")
}
/*
Notice not a composable. Just an extended method for NavGraphBuilder.
Also notice that what would have been `composable(StartupNavigationScreens.Main.route)` is now `route = StartupNavigationScreens.Main.route`
/*
fun NavGraphBuilder.mainGraph(navController: NavController) {
navigation(startDestination = MainNavigationScreens.Home.route, route = StartupNavigationScreens.Main.route) {
composable(MainNavigationScreens.Home.route) { Home(navController) }
composable(MainNavigationScreens.Secondary.route) { Secondary(navController) }
}
}
Navigation.kt
### Navigation Breakdown
So here you will notice a few things:
- I have the sealed classes in this file
- We use NavGraphBuilder.graphName
- The route for the `mainGraph` is equal what would have been the
composable route
To start with readability I think this is the perfect way to setup your
navigation files. If you needed to nest another graph for say a profile
workflow then I would highly recommend making a new file and doing the
work there. The way navigation is written can make the readability
become very confusing for other people to read so let\'s try to keep it
as clean as possible here.
Now, back to the code breakdown\...notice the route from
`StartupNavigationScreens` being the way to connect to the main graph.
Now you might be asking \"why is this?\". I truly don\'t know. I\'m
assuming it has something to do with the route naming. Every `route =`
is a way to give a graph a unique name. In this case your saying this
`route name = main graph` and at that point the graph details take over.
Lastly I\'ll mention `NavGraph.graphName`. Notice that this is not a
composable function, BUT in `MainActivity.kt` the main navigation is
inside a composable. That is because we are extending the functionality
of the navHost. If you ctl + click on `NavGraphBuilder` you can see the
break down yourself. The main thing I want you to remember is the name
after the `.` is what you use to call the nested graph, and this is not
a composable function.
Conclusion
----------
TLDR: I want JC to use the previous navigation graph. If the purpose is
getting up and running in a timely fashion then I think that step is
imperative.
I hope I\'ve brain dumped enough of my lessons so you can also
understand nested graphs. The documentation was really confusing to me
because I was at first using bottom navigation (where they recommend
sealed classes for screens), but the main navigation section isn\'t
written with that concept in mind.
I kinda want JC to succeed but I think issues like this where it takes
longer to connected the dots to solve my problems will be the reason I
go back to \"traditional\" Android apps. If Google doesn\'t want this I
highly recommend that they pivot faster for clarity.
Resources
---------
Check out my jetpack compose template repo here (this code came from
LoginFlow): <https://github.com/Keheira/Jetpack-Compose-Templates>
P.S. When are we getting ide templates for JC Google??????