Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to avoid bug with navigator.popbackstack [duplicate]

I have two screens, A and B in Master/Detail. B (Detail) has an actionbar on top with a back icon to go back to Master. However, I've noticed that if I doubletap the back icon, it goes back to A (as expected) and then the screen goes completely blank.

My current code to access screen B is as follows

NavHost(navController = navController, startDestination = ScreenRouter.ScreenA.route)
{
    composable(ScreenRouter.PokemonList.route) {
                PokedexList(showPokemonDetail = { myID ->
                navController.navigate(
                        route = ScreenRouter.ScreenB.createRoute(myID)
                    )
                })

            }

    composable(route = ScreenRouter.ScreenB.route) { backStackEntry ->
       val myID = backStackEntry.arguments?.getString("id")
       requireNotNull(myID)    
       ScreenB(
          id = myID, 
          navigateUp = {navController.popBackStack()}
       )
    }
}

It feels like by the time I'm in Screen B, there are two screens loaded in memory. One popbackstack leads to Screen A. An additional popbackstack removes also that and leaves me in this blank "no-screen" situation.

How can I prevent this in a good practices way?

like image 692
Frank Avatar asked Dec 28 '25 06:12

Frank


1 Answers

This is what's causing your problem:

https://developer.android.com/guide/navigation/backstack#handle-failure

When the popBackStack() returns false, a subsequent call to NavController.getCurrentDestination() returns null. This means the app has popped the last destination off the back stack. In this case, the user sees only a blank screen.

This can occur in the following cases:

popBackStack() did not pop anything from the stack.
popBackStack() did pop a destination off the back stack and the stack is now empty.

So you can try implementing logic that evaluates whether there is something available in the backstack to pop.


Here is an extension method that you can use instead of popBackStack(), so if there is nothing in the back-stack activity will be finished instead of the blank screen.

/**
 * Attempts to pop the controller's back stack.
 * If the back stack is empty, it will finish the activity.
 *
 * @param context Activity context.
 */
fun NavController.popBackStackOrFinish(context: Context) {
    if (!popBackStack()) {
        (context as Activity).finish()
    }
}
like image 181
Roberto Betancourt Avatar answered Dec 30 '25 23:12

Roberto Betancourt