Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to stop Jetpack Compose Navigation executing composable twice per click and why

I have created a Jetpack compose navigation as follows:

val navController = rememberNavController()

Scaffold(
    bottomBar = { /* BottomBar code here */ }
){ innerPadding ->

    NavHost(
         navController = navController,
         startDestination = "navigation",
         modifier = Modifier.padding(innerPadding)
    ){

        composable("home") { Log.d(TAG, "Show home screen") }

        composable("account") { Log.d(TAG, "Show account screen") }

        composable("settings") { Log.d(TAG, "Show settings screen") }

    }

}

My problem is when ever I click on a nav item, the log message on the composable() function is printed twice per click in logcat. I may have missed something on the documentation. Why is this happening & how can I fix it?

like image 243
Nic Avatar asked Dec 09 '25 22:12

Nic


2 Answers

I had the same problem and I cal solve it using NavOptions

 navController.navigate(
                ...,
                navOptions = navOptions {
                    launchSingleTop = true
                }
            )
like image 166
Huan Avatar answered Dec 11 '25 12:12

Huan


You are in a typical case with side effects. Check compose documentation with the recomposition here : https://developer.android.com/jetpack/compose/mental-model#parallel

Based on your code, if you want to display the debug log once when click on the "Display account button" :

val navController = rememberNavController()

Scaffold(
    bottomBar = {
        Button(onClick = { navController.navigate("account") }) {
            Text(text = "Display account")
        }
    }
){ innerPadding ->
    NavHost(
        navController = navController,
        startDestination = "navigation",
        modifier = Modifier.padding(innerPadding)
    ){
        composable("home") { Log.d(TAG, "Show home screen") }
        composable("account") {
            val isLogPrinted = remember { mutableStateOf(false) }
            if (!isLogPrinted.value) {
                Log.d(TAG, "Show account screen")
                isLogPrinted.value = true
            }
        }
        composable("settings") { Log.d(TAG, "Show settings screen") }
        composable("navigation") { Log.d(TAG, "Show navigation screen") }
    }
}

You can also put the log in your "onClick" function.

like image 29
Guillaume Muret Avatar answered Dec 11 '25 12:12

Guillaume Muret



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!