https://kotlinlang.org logo
#compose
Title
# compose
m

Mehdi Haghgoo

11/08/2020, 8:46 PM
I am getting some weird error with the new Compose Navigation.
Copy code
NavHost(navController, startDestination = "home"){
        composable("new-item"){NewItem(navController)}
        composable("profile/{name}", listOf(navArgument("name"){type = NavType.StringType}))
        {navBackStackEntry ->
            Profile(navBackStackEntry.arguments?.getString("name").toString())
        }

        composable("home?costName={costName}&costValue={costValue}",
                arguments = listOf(navArgument("costName"){nullable = true}, navArgument("costValue"){type = NavType.IntType; defaultValue = 0})){
            navBackStackEntry ->  Home(navController, navBackStackEntry.arguments?.getString("costName"), navBackStackEntry.arguments?.getInt("costValue"))
        }
    }

//    java.lang.IllegalArgumentException: navigation destination 150924488 is not a direct child of this NavGraph
//    at androidx.navigation.NavGraphNavigator.navigate(NavGraphNavigator.java:66)
i

Ian Lake

11/08/2020, 8:52 PM
home
!=
home?costName={costName}...
- those need to match exactly
m

Mehdi Haghgoo

11/08/2020, 8:52 PM
but home?costName is not optional arguments?
Sometimes I need to pass it some arguments and sometimes no arguments.
i

Ian Lake

11/08/2020, 8:54 PM
There's no problem with how you're defining home, it is the start destination that isn't matching - the ID generated from the route is based on the whole string
m

Mehdi Haghgoo

11/08/2020, 9:02 PM
Matching them does not seem to help either 😞
Copy code
NavHost(navController, startDestination = "home?costName=null&costValue=0"){
        composable("new-item"){NewItem(navController)}
        composable("profile/{name}", listOf(navArgument("name"){type = NavType.StringType}))
        {navBackStackEntry ->
            Profile(navBackStackEntry.arguments?.getString("name").toString())
        }

        composable("home?costName={costName}&costValue={costValue}",
                arguments = listOf(navArgument("costName"){nullable = true}, navArgument("costValue"){type = NavType.IntType; defaultValue = 0})){
            navBackStackEntry ->  Home(navController, navBackStackEntry.arguments?.getString("costName"), navBackStackEntry.arguments?.getInt("costValue"))
        }
    }

//    java.lang.IllegalArgumentException: navigation destination -423783418 is not a direct child of this NavGraph
i

Ian Lake

11/08/2020, 9:15 PM
What I mean is that the strings need to match exactly:
startDestination="home?costName={costName}&costValue={costValue}"
The start destination is trying to find the
composable
with the exact same route. It has nothing to do with starting arguments (which aren't supported at the moment - you'll always get only your default values for arguments for the start destination), etc.
In general, the start destination of your app should very much be a unique, recognizable first entry point for users launching your app, which, tbh, doesn't lend itself at all to optional arguments or something that you'd reuse later in your app, but obviously without details on exactly how your app is set up, it is hard to say if that rule of thumb applies here
m

Mehdi Haghgoo

11/09/2020, 5:35 AM
@Ian Lake I agree. I think I should remove parameters for the start destination and instead pass a viewmodel to the composable so that it can save costName and costValue in the NewItem composable for example rather than returning them to home destination, which I intended to do initially. So, is it a bad idea to use navigation to return some data to a destination in compose like what we were used to in classic Android?
i

Ian Lake

11/09/2020, 5:37 AM
You'd want to use Navigation's API for returning a result, which works perfectly in Compose: https://developer.android.com/guide/navigation/navigation-programmatic#returning_a_result
❤️ 2
You should never have been using
navigate()
for returning a result
❤️ 1
3 Views