Compose-Navigation: Remove previous composable from stack before navigating

Viewed 10972

I'm using compose-navigation(alpha09) to handle the navigation between composables

I want to remove the Splash screen when moving to the next destination (I don't want the back pressed to get back to Splash)

Following attempts did not work as expected:

navHostController.navigate(Route.login.id) {
    navHostController.graph.clear()
}
navHostController.navigate(Route.login.id)
navHostController.graph.clear()
val currentDest = navHostController.currentDestination
navHostController.navigate(Route.login.id)
if (currentDest != null) {
   navHostController.graph.remove(currentDest)
}

So how can I remove the Splash screen and then move to next?

6 Answers

In Jetpack Compose 1.0.0-rc01 to navigate and remove previous Composable from back stack You can use:

navController.navigate(Screens.Login.name) {
    popUpTo(Screens.Splash.name) {
        inclusive = true
    }
}

The above code will navigate from the Splash screen to Login and will pop everything up, including the Splash screen.

Navigate to a composable - docs

For v1.0.0-alpha09 (And 1.0 stable)

Using popUpTo(0) you can clear the stack before navigating to the next destination. So:

navHostController.navigate(Route.login.id) {
    // popUpTo = 0 // DEPRECATED
    popUpTo(0)
}

For a consistent reusable function that does not need to be aware of the current route, use this NavOptionsBuilder extension function

fun NavOptionsBuilder.popUpToTop(navController: NavController) {
    popUpTo(navController.currentBackStackEntry?.destination?.route ?: return) { 
        inclusive =  true
    }
}

^ Similar to other answers, it popUpTo the current route, but rather than needing to name the specific current route, it instead gets it from the backstack entry.

Now you can use it like so:

navController.navigate(ScreenRoutes.Login.route) { popUpToTop(navController) }

^ That example navigates to Login, and should clear the entire backstack before it.

For clearing all back stack

To remove multiple composable screens from the stack use the below snippet

navController.navigate(ScreenRoutes.Login.route){
                    popUpTo(navController.graph.findStartDestination().id){
                        inclusive = true  }}

Or To keep Home in back stack

navController.navigate(ScreenRoutes.SelectCourseLayout.route){
    popUpTo(ScreenRoutes.Home.route)
}

Jetpack Compose v1.0.5

navController.backQueue.removeIf { it.destination.route == "Splash" }
navController.popBackStack()

After so many try, I've found the better way to clear the back stack during the logout scenario. Most of the production app will clear the splash or sign in screen as soon as we navigate to Home screen and there would be a multiple way to land into Home screen as well.

So, we may not know the initial screen to perform the popupTo. If there is a bottom bar, then story would be too difficult as well.

Here is a magic could that work all the scenario

 val firstBackStackRoute = navController.backQueue.firstOrNull()?.destination?.route
 firstBackStackRoute?.let { 
        navController.popBackStack(firstBackStackRoute, true)
  }
Related