androidandroid-jetpack-composeandroid-jetpackandroid-jetpack-navigation

Why does composable call twice during passing data between two screen


I have an Issue while passing data between two screen. Currently log called twice from below code

        composable(Screens.VisionBoardNameChooserScreen.route) {
            userViewModel.getUserNameUseCase()
            val userName = userViewModel.fetchUserName.collectAsState()

            VisionBoardNameChooserScreen(userName, submitVisionBoard = { boardName ->
                visionBoardNameViewModel.saveBoard(
                    BoardData(
                        visionBoardName = boardName
                    )
                )
                navController.navigate(Screens.AddSectionScreen.route + "/$boardName")
            }, onBackPressClicked = {
                navController.popBackStack()
            })

        }

        composable(Screens.AddSectionScreen.route + "/{boardName}") {navBackStack ->

            val boardName = navBackStack.arguments?.getString("boardName")
            Log.i("NAVTAG", "VisionBoardNavigation: $boardName")

            AddSectionScreen(onBackPressClicked = {
                navController.popBackStack()
            }, submitSection = {

                // TODO: Add Data Into Database and Then Redirect To Next Screen

                navController.navigate(Screens.HomeScreen.route)
            })
        }

Here is My Logcat enter image description here


Solution

  • In jetpack compose any composable recomposes multiple times on the screen. And if you are performing some work inside the navigation composable then it also called multiple times as Log does in your case. To avoid this you can do that particular work inside LaunchedEffect and then pass the data in the Screen. Composable cannot be created inside LaunchedEffect and hence, by this way you can save multiple calls but screen will recompose with the provide data.

    Example:
    Replace your line Log.i("NAVTAG", "VisionBoardNavigation: $boardName") with

    // Pass any value as the keys
    LaunchedEffect(key1 = true) {
        Log.i("NAVTAG", "VisionBoardNavigation: $boardName")
    }
    

    The LaunchedEffect will only called again if the provided keys(true in our case) are changed. As we can also pass multiple keys as the parameter. And in our case true is not changing so it will just run once. That's how you can do single time task using LaunchedEffect.