Android Jetpack Compose and Nesting Navigation

Putting composables into an appropriate structure

Tomáš Repčík
Better Programming

--

Photo by Marc Sendra Martorell on Unsplash

In the previous article, the basics of navigation with NavHost and NavController have been described. However, with more complex apps, the app's navigation graph could get messy and lead to redundant mistakes in code. The app structure can make it much more testable, scalable, and easier to fix. Go here for the basic setup:

The most straightforward approach would be to put all the screens into one NavHost. But we can do better with the nesting of the graphs.

As it goes in programming, we want to separate our logic. The multiple paths can be grouped into graphs like Introduction, Main Screen, or others. So, let’s take a look at it.

The targeted composition of the navigation

The demonstration will be done on a simple introduction workflow and main home screen, which can go to other screens. Firstly, we want to introduce the app, motivate the user and give them some recommendations for usage. Afterward, the user can use the app in the main navigation.

The split of the navigation can be done like this:

Screen-by-screen representation

Creating the Graphs

The graph is created with the NavGraphBuilder, which can declare composables and separate them into separate files. Moreover, it can be named in any way you want. The builder wraps the navigation component with its destinations.

Route is unique path to the screen/composable. Every screen/composable has its route. However, the destination can appear in the documentation or as parameter name. In other words, every screen is destination to which we need to take some unique route. The same goes for the sole graphs, where every graph has its own route. That is why we define, for example, INTRO_ROUTE to graph and INTRO_WELCOME_SCREEN to specific screen/composable.

With graphs created, we can declare them in the root activity of the app. The graphs are wrapped in a single NavHost. The navController is initialized at the root and passed to every graph so it is shared among them. Every screen should have access to the navController too.

MainActivity, which includes navigation graphs

From now on, all the screens will contain only two buttons to move forward and go backward for simplicity. The only thing that will change is the onClick action of the buttons. For example:

Screen example where we will change only onClick methods

Navigation Among the Screens

Now, the screens and graphs are implemented. The last missing piece is navigation from one screen to another. The example will follow the user flow.

Moving through the intro to the main home screen

The start destination is marked as the intro to the app, so the intro graph is picked as starting destination. If a user wants to move out of the current welcome screen, standard .navigate() and .popStack() are enough to use.

navController.navigate(IntroNav.INTRO_MOTIVATION_SCREEN)
// or to go back
navController.popBackStack()

Navigating through the intro, the stack fills with all the screens. If we moved to another graph and clicked the back button, we would still get to the previous screen. Navigating to the home screen, the stack needs to be cleaned from the intro screen. Here comes the popUpTo() function and NavOptionsBuilder. The builder, a parameter of the navigate function, can pop the stack till the beginning of the graph. To remove one graph and navigate to another:

// moving to the main graph route
navController.navigate(MainNav.MAIN_ROUTE) {
// removing everything reagrding intro (incliding the intro route itself)
popUpTo(IntroNav.INTRO_ROUTE)
}
Example of moving around the app.

It does not mean you cannot nest two graphs into each other. Feel free to create another graph and navigate to it without popUpTo(). The back button will work in the same manner as you anticipate.

Advice

  • Spend some time and think about the user flow in the app
  • Try to make it easier for you. The navigation will be easier for your end user too.
  • Spend some time with your actual perspective/actual user, and you will be surprised sometimes

Thanks for reading, and stay tuned for more!

Resources

More from Android development:

Android development

21 stories

--

--

https://tomasrepcik.dev/ - Flutter app developer with experience in native app development and degree in biomedical engineering.