Search code examples
androidnavigationandroid-jetpack-compose

How to exit the application in navigation composable in Android


I have an application which has three screens. The first one is Onboarding after that there is Home and then Profile. If the information is not present, the app opens to Onboarding and if already there, then it goes to Home.

The home page has a button which navigates to profile. The profile page has a log out button and when the user presses it, it goes back to Onboarding.

My problem is that after the user presses the log out button, it goes back to Onboarding as expected, but when you press the back button while on Onboarding screen, instead of exiting the app, it goes back to Profile screen. Here is the navigation:

@Composable
fun NavigationComposable() {

    val context = LocalContext.current
    val sp = PreferenceManager.getDefaultSharedPreferences(context)
    val firstName = sp.getString("firstName", null)
    val lastName = sp.getString("lastName", null)
    val email = sp.getString("email", null)

    val navController = rememberNavController()
    if (firstName == null && lastName == null && email == null) {
        NavHost(
            navController = navController,
            startDestination = Onboarding.route
        ) {
            composable(Onboarding.route) {
                Onboarding(navController = navController)
            }
            composable(Home.route) {
                Home(navController = navController)
            }
            composable(Profile.route) {
                Profile(navController = navController)
            }
        }
    } else {
        NavHost(
            navController = navController,
            startDestination = Home.route
        ) {
            composable(Home.route) {
                Home(navController = navController)
            }
            composable(Profile.route) {
                Profile(navController = navController)
            }
            composable(Onboarding.route){
                Onboarding(navController = navController)
            }
        }

    }
}

Here is the Profile

@Composable
fun Profile(navController: NavController) {

      Column(
                modifier = Modifier.fillMaxWidth().padding(10.dp),
                horizontalAlignment = Alignment.CenterHorizontally
            ) {
                Button(onClick = {
                    PreferenceManager.getDefaultSharedPreferences(context).edit().clear().apply();
                    navController.navigate(Onboarding.route)

                }) {
                    Text(text = "Log out")
                }
            }
      }

How can I change it to exit the app when on the Onboarding page?


Solution

  • I had tried your code. Please make use of NavOptions to set popupTo and popupinclusive of Navigation compose.

    Here is the code:

    @Composable
    fun NavigationComposable() {
    
        val context = LocalContext.current
        val sp = PreferenceManager.getDefaultSharedPreferences(context)
        val firstName = sp.getString("firstName", null)
        val lastName = sp.getString("lastName", null)
        val email = sp.getString("email", null)
    
        val navController = rememberNavController()
        val startDestination = if (firstName == null && lastName == null && email == null) {
            Onboarding.route
        } else {
            Home.route
        }
        NavHost(
            navController = navController,
            startDestination = startDestination
        ) {
            composable(Onboarding.route) {
                Onboarding(navController = navController)
            }
            composable(Home.route) {
                Home(navController = navController)
            }
            composable(Profile.route) {
                Profile(navController = navController)
            }
        }
    }
    

    Note: Here I get the start destination using a condition. It is a slight modification of your code. If applicable, make use of this.

    Here is the code of Profile and Onboarding

    1. Profile Screen

      @Composable
      fun Profile(navController: NavController) {
      
          Column(
              modifier = Modifier.fillMaxWidth().padding(10.dp),
              horizontalAlignment = Alignment.CenterHorizontally
          ) {
              Button(onClick = {
                  val navOptions = NavOptions.Builder().setPopUpTo(Home.route, true).build()
                  navController.navigate(Onboarding.route, navOptions)
      
              }) {
                  Text(text = "Log out")
              }
          }
      }
      
      
    2. OnBoarding Screen

      @Composable
      fun Onboarding(navController: NavController) {
      
          Column(
              modifier = Modifier.fillMaxWidth().padding(10.dp),
              horizontalAlignment = Alignment.CenterHorizontally
          ) {
              Button(onClick = {
                  val navOptions = NavOptions.Builder().setPopUpTo(Onboarding.route, true).build()
                  navController.navigate(Home.route, navOptions)
      
              }) {
                  Text(text = "To Home")
              }
          }
      }
      

    As you can see, in both the screens, when you try to navigate, I have used navOptions to popUp the screen in the back stack. This worked for me.