0

I've been trying to send a destination with optional parameter to navigation start destination for 2 days, but I found out that this is not possible. The start destination of the navigation had to match the character-by-character route, so it had to be exactly the same, so I've been encountering this error for 2 days.

java.lang.IllegalArgumentException: navigation destination verification_phone_code_screen?isRedirectFromLoginOrSplash=true is not a direct child of this NavGraph

What I did:

I wrote a function that determines the screen to go to in MainActivity, it specifies where to go according to these conditions.

private fun navigateIfNeeded(response: NavigateState, isTokenExist:Boolean): String {


        return when {
            !isTokenExist -> RegisterScreen.SignUpStartRegisterScreen.route
            response.hasValidation == 0 -> "${RegisterScreen.SignUpVerificationPhoneCodeScreen.route}?$EMAIL={$EMAIL}&$PHONE={$PHONE}&$IS_REDIRECT_FROM_LOGIN_OR_SPLASH={$IS_REDIRECT_FROM_LOGIN_OR_SPLASH}" 
            response.hasValidation == 1 -> {
                when (response.eatingHabit) {
                    0 -> {
                        if (response.weight == 0 || response.goalWeight == 0) {
                            return RegisterScreen.SignUpDailyCalorieGoalScreen.route
                        } else{
                            return DASHBOARD_ROUTE
                        }
                    }
                    else -> RegisterScreen.SignUpPaymentScreen.route
                }
            }
            else -> DASHBOARD_ROUTE
        }
    }

response.hasValidation == 0 -> "${RegisterScreen.SignUpVerificationPhoneCodeScreen.route}?$EMAIL={$EMAIL}&$PHONE={$PHONE}&$IS_REDIRECT_FROM_LOGIN_OR_SPLASH={$IS_REDIRECT_FROM_LOGIN_OR_SPLASH}"

When the following condition works, it gives an error here, of course, since I gave the full path, it goes smoothly, but what I want to do here is to pass the true booelan value to the IS_REDIRECT_FROM_LOGIN_OR_SPLASH parameter, but this is not possible as far as I understand

I'm sending the start destination to my Root NavGraph like this MainActivity setContent setContent {

            AppTheme {
                navHostController = rememberNavController()
                Surface(
                    modifier = Modifier
                        .fillMaxSize()
                ) {
                    RootNavGraph(navHostController = navHostController, startDestination)
                }
            }
        }

and I get it in Root NavGraph and set it like this

If the incoming startDestination value is dashboard route, I say go to DASHBOARD_ ROUTE, if it is not dashboard route, I go to REGISTER_LOGIN_ROUTE. There is no problem here

@Composable
fun RootNavGraph(
    navHostController: NavHostController,
    startDestination: String,
) {

    val sharedViewModel: SharedViewModel = viewModel()

    val startRoute =
        if (startDestination != DASHBOARD_ROUTE) REGISTER_LOGIN_ROUTE else DASHBOARD_ROUTE

    NavHost(
        navController = navHostController,
        startDestination = startRoute,
        route = ROOT_ROUTE
    )
    {
        registerLoginNavGraph(navHostController, sharedViewModel, startDestination)
        dashBoardNavGraph(navHostController, sharedViewModel)
    }
}

where i want to go next is the place i ask in this problem so SignUpVerificationPhoneCodeScreen registerLoginNavGraph is also

hear is my registerLoginNavGraph

fun NavGraphBuilder.registerLoginNavGraph(
    navHostController: NavHostController,
    sharedViewModel: SharedViewModel,
    startDestination: String,
) {

    val _startDestination =
        if (startDestination == "")
            RegisterScreen.SignUpStartRegisterScreen.route
        else
            startDestination


    navigation(
        startDestination = _startDestination,
        route = REGISTER_LOGIN_ROUTE
    ) {
       .
       .
       .
     composable(
            route = "${RegisterScreen.SignUpVerificationPhoneCodeScreen.route}?$EMAIL={$EMAIL}&$PHONE={$PHONE}&$IS_REDIRECT_FROM_LOGIN_OR_SPLASH={$IS_REDIRECT_FROM_LOGIN_OR_SPLASH}",
            arguments = listOf(
                navArgument(EMAIL) {
                    type = NavType.StringType
                    defaultValue = ""
                },
                navArgument(PHONE) {
                    type = NavType.StringType
                    defaultValue = ""
                },
                navArgument(IS_REDIRECT_FROM_LOGIN_OR_SPLASH) {
                    type = NavType.BoolType
                    defaultValue = false
                }
            )
        ) { backStackEntry ->

            VerificationPhoneCodeRoute(
                navHostController,
                sharedViewModel,
                userPhone = backStackEntry.arguments?.getString(PHONE),
                userEmail = backStackEntry.arguments?.getString(EMAIL),
                isRedirectFromLoginOrSplash = backStackEntry.arguments?.getBoolean(
                    IS_REDIRECT_FROM_LOGIN_OR_SPLASH
                )
            )
        }

For example, when startDestination comes with parameters, it looks like this:

 "${RegisterScreen.SignUpVerificationPhoneCodeScreen.route}?$IS_REDIRECT_FROM_LOGIN_OR_SPLASH=true"

it gives this error

java.lang.IllegalArgumentException: navigation destination verification_phone_code_screen?isRedirectFromLoginOrSplash=true is not a direct child of this NavGraph

Is there any way to solve this problem here? I want to send a parameter or value to verification_phone_code_screen that I can only check. I can do this another way, but I can't think of a solution. Most likely sending startDestination with parameters won't work. How can I do this in any way? Can you show me a solution? Please

NewPartizal
  • 604
  • 4
  • 18
  • Do you want your start destination to be dynamic based on some argument? Like for exemple if the user is signed out or new the app will start in the sign in screen and if the user is already signed in the app will start directly from the main screen of exemple? – Ayman Ait Jun 22 '23 at 15:33

0 Answers0