Navigation: Multiple back stacks

Murat Yener
Android Developers
Published in
3 min readJun 15, 2021

--

Welcome to another article in the second MAD Skills series on Navigation! In this article we’ll take a look at a highly requested feature, multiple back stack support for Navigation. If you prefer this content in video form, here is something to check out:

Intro

Let’s say your app uses BottomNavigationView. With this change, when the user selects another tab, the back stack for the current tab will be saved and the back stack for the selected tab will be restored seamlessly.

Starting with version 2.4.0-alpha01, the NavigationUI helpers support multiple back stacks without any code change. This means that if your app uses the setupWithNavController() methods for BottomNavigationView or NavigationView, all you need to do is to update the dependencies and multiple back stack support will be enabled by default.

Multiple Back Stack Support

Let’s see this in action using the Advanced Navigation sample from this repo.

The app consists of 3 tabs and each tab has its own navigation flow. To support multiple back stacks in earlier versions of Navigation, we needed to add a set of helpers in NavigationExtensions file to this sample. With these extensions, the app keeps a separate NavHostFragment with its own back stack for each tab and swaps between them as the user switches from one tab to another.

Let’s see what happens if I remove these extension functions. To do this I delete the NavigationExtensions class and remove all uses, switching over to the standard setupWithNavController() method from NavigationUI for connecting our BottomNavigationView to the NavController.

class MainActivity : AppCompatActivity() {

private lateinit var navController: NavController
private lateinit var appBarConfiguration: AppBarConfiguration

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

val navHostFragment = supportFragmentManager.findFragmentById(
R.id.nav_host_container
) as NavHostFragment
navController = navHostFragment.navController

// Setup the bottom navigation view with navController
val bottomNavigationView = findViewById<BottomNavigationView>(R.id.bottom_nav)
bottomNavigationView.setupWithNavController(navController)

// Setup the ActionBar with navController and 3 top level destinations
appBarConfiguration = AppBarConfiguration(
setOf(R.id.titleScreen, R.id.leaderboard, R.id.register)
)
val toolbar = findViewById<Toolbar>(R.id.toolbar)
setSupportActionBar(toolbar)
toolbar.setupWithNavController(navController, appBarConfiguration)
}

override fun onSupportNavigateUp(): Boolean {
return navController.navigateUp(appBarConfiguration)
}
}

I also combine the 3 separate navigation graphs into a single graph by using the include tag. Now our activity’s layout just includes a single NavHostFragment with our single graph.

<navigation
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/nav_graph"
app:startDestination="@+id/home">

<include app:graph="@navigation/home"/>
<include app:graph="@navigation/list"/>
<include app:graph="@navigation/form"/>


</navigation>

When I run the app, this time bottom tabs do not keep their state and reset its back stack as I switch to other tabs. With NavigationExtentions removed, the app lost multiple back stack support.

Now I update the version of navigation and fragment dependencies.

versions.fragment = "1.4.0-alpha01"
versions.navigation = "2.4.0-alpha01"

Once gradle sync is complete, I run the app again and I can see that each tab keeps its state when I navigate to another tab. Notice this behavior is enabled by default.

Finally, to verify that everything works, let’s run the tests. This app already has several tests to verify the multiple back stack behavior. I run BottomNavigationTest and watch different tests running and testing the bottom navigation behavior.

Voila, all our tests pass!

Summary

That’s it! If your app uses BottomNavigationView or NavigationView and you’ve been waiting for multiple back stack support, all you need to do is to update your navigation and fragment dependencies. No code change is needed!

If you’re doing something more custom, there are also new APIs to enable saving and restoring the back stack which you can learn more in this article.

If you are curious to learn more about the underlying APIs and what needed to be changed to support multiple back stacks, you can check out this article.

Thanks for following this Navigation series!

--

--