Jetpack Compose passing encoded String to navController as argument causes IllegalArgumentException
Asked Answered
O

0

1

I checked out answers here and here to pass an Object from one composable to another and passing an @Serializable object as String from one composable to another but get the resulting error

  java.lang.IllegalArgumentException: Navigation destination that matches request NavDeepLinkRequest{ uri=android-app://androidx.navigation/detail/{"id":3,"email":"[email protected]","first_name":"Emma","last_name":"Wong","avatar":"https://reqres.in/img/faces/3-image.jpg"} } cannot be found in the navigation graph NavGraph(0x0) startDestination={Destination(0x60276fc4) route=start_destination}
        at androidx.navigation.NavController.navigate(NavController.kt:1530)

Data class

@Serializable
data class User (
    val id : Int,
    val email : String,
    val first_name : String,
    val last_name : String,
    val avatar : String
)

it's sample from reqres.in api, and NavHost to navigate between composables is

NavHost(
    navController = navController,
    startDestination = "start_destination",
    modifier = Modifier.padding(paddingValues)
) {
    composable(route = "start_destination") {
        ListScreen() { user ->
            val json: String = Json.encodeToString(user)
            navController.navigate("detail/$json")
        }
    }

    composable(route = "detail/{user}", arguments = listOf(
        navArgument("user") {
            type = NavType.StringType
        }
    )) { backStackEntry ->

        val arguments = requireNotNull(backStackEntry.arguments)
        val user = Json.decodeFromString<User>(string = arguments.getString("user")!!)
        DetailScreen(user = user)
    }
}

crash occurs when navController.navigate("detail/$json") is called.

Ormiston answered 14/9, 2021 at 11:12 Comment(7)
Does this answer your question? How pass parcelable argument with new version of compose navigation?. I know that you're trying to encode an object in a different way, but the answer is valid in both cases.Seroka
@PhilipDukhov thanks for the suggestions but my question why parsing it causing an exception with the data encoded from an Object with kotlin serialize. I tried with another sample data class and it works fine. This is not the same question or another answer is required. I wonder the cause for navigation to not find the json string i providedOrmiston
Route is analog of a URL, and you can't just paste any string inside and expect it to be parsed. In your case I think that { and } are the symbols that navigation fails to parse clearly. You shouldn't work with compose navigation in this way, just pass object id and then read it from a repository. Check out this answer, it's made by Compose maintainer.Seroka
I checked out the answer it suggests to expose every data source you have repository or ViewModel in my instance to NavHost, that's actually not i want and i'm not passing a Parcelable as stated as anti-pattern but passing it as String which only exposes the data itself to nav graph. And other answers that require using currentBackStackEntry are not straight forward and as mentioned in the comments are not working in same cases. Also passing a String is not working but as you suggested Route is analog of a URL so it might be not working due to data class itself containing a url for avatarsOrmiston
Try encoding your string as described in this answer.Seroka
After removing the avatar which containshttps://reqres.in/img/faces/3-image.jpg, from data class it works fine, changed user.avatar with URLEncoder.encode("http://alphaone.me/", StandardCharsets.UTF_8.toString()) it didn't work but it's apparent that source of problem is data class containing url. So if a data class contains url it's better to stay away from coding/decoding data class.Ormiston
@PhilipDukhov is actually right. It works just fine. All I had to do is just encode the url, update the data, convert it to json by using Gson and pass it with the route -> /data.Irrigation

© 2022 - 2024 — McMap. All rights reserved.