26

I found out that the composable screens are getting recomposition multiple times during navigation from Navhost compose the following example shows how I'm integrating the navigation with logs to identify how many time the function is getting called,

internal sealed class Screen(val route: String) { object Splash : Screen("splash") object Login : Screen("login") object Credentials : Screen("credentials/{type}") { fun createRoute(type: String) = "credentials/$type" } } @Composable fun HostNavGraph( modifier: Modifier = Modifier, startDestination: String = Splash.route, ) { val navController = rememberNavController() val vm: CredentialsViewModel = getViewModel() NavHost(navController = navController, startDestination = startDestination, modifier = modifier) { composable(route = Splash.route) { Log.e("composable", " Splash") SplashScreen(openLogin = { navController.navigate(Login.route) }, openRegistration = { type -> navController.navigate(Credentials.createRoute(type)) }) } composable(route = Login.route) { Log.e("composable", " Login") val context = LocalContext.current LoginScreen(openRegistration = { type -> navController.navigate(Credentials.createRoute(type)) { popUpTo(Splash.route) { inclusive = false } } }, openWebView = { openWebView(context, it) }) } //.. } } 

And after running the code this is how the navigation behaves after Opening Splash once then Opening LoginScreen once

15:05:14 E/composable: Splash 15:05:14 E/composable: Splash 15:05:25 E/composable: Splash 15:05:25 E/composable: Login 15:05:26 E/composable: Splash 15:05:26 E/composable: Login 15:05:26 E/composable: Login 

I also tried some Google examples with Navigation compose, it behaves the same way, so is this an intended behavior?? or is it a bug
navigation_version = '2.4.0-alpha08'

4
  • 2
    any solutions about this? Commented Apr 1, 2022 at 16:14
  • 1
    How did you solve this? Commented Oct 17, 2022 at 12:48
  • Plz guide me how to solve this issue. Commented Dec 22, 2022 at 13:22
  • 2
    It was marked won't fix at issuetracker.google.com/issues/225987040 Commented Jul 7, 2023 at 6:38

2 Answers 2

10

I'm not sure but I think the NavHost has a built-in animation whenever there is a transition. and with the animation, the recomposition could happen frequently as often as every frame.

A composable function might be run quite frequently, as often as every frame of an animation.

**Android compose

Sign up to request clarification or add additional context in comments.

Comments

3

It's not a bug. NavHost is a composable, So naturally it can be composed and recomposed several times! If you want to do a one-time action in a composable lifecycle, use LaunchedEffect.

composable(route = Login.route) { LaunchedEffect(key){ // relaunched every time its parameter changes //It's a good idea to pass the user ID as an argument and use it as the key Log.e("composable", " Login") } ... }) 

Log.e() is a side effect because it affects the state outside the scope of the composable function. A side effect is an operation that does not affect the UI directly, such as logging.

5 Comments

this is one of the recommended suggestions found here. youtube.com/watch?v=Kp-aiSU8qCU
@ucMax, question why the "Log.e() is a side effect ", the log does not touch any "state", does it? thanks in advance!
@lannyf In Jetpack Compose, side effects are considered operations that interact with the outside world or alter the environment outside the scope of the composable function itself. This includes things like logging, network calls, database operations, etc...
I believe only if the Log has used the state outside the scope of the composable, otherwise it is not.
@lannyf Yes, if the login action is purely local to the composable and doesn't interact with external systems or shared state, it can be considered part of the regular UI state flow.

Start asking to get answers

Find the answer to your question by asking.

Ask question