Hi I'm pretty new to Android and Jetpack Compose so bear with me.
I have a screen with posts and when I click on a post I want to navigate to a separate screen of that post only.
Post data class
@Serializable
data class Post(
val id: Int,
val imageUrl: String,
val postedDate: String,
// val likes: List<Like> <--- this doens't work
)
Like data class
@Serializable
data class Like(
val user: User
)
In my MainActivity:
setContent {
AppTheme {
val navController = rememberNavController()
NavHost(navController = navController, startDestination = FeedScreen) {
composable<FeedScreen> {
FeedScreen(navController)
}
composable<Post> { backStackEntry ->
val post: Post = backStackEntry.toRoute()
PostScreen(post, onGoBack = { navController.popBackStack() })
}
}
}
And in my feed screen
...
Column(
...
) {
posts.forEach { p ->
Post(post = p, onClickCard = {
navController.navigate(p)
})
}
}
This seems to work pretty well but if I uncomment the likes attribute, the app fails at runtime with
java.lang.IllegalArgumentException: Cannot cast likes of type kotlin.collections.List to a NavType. Make sure to provide custom NavType for this argument.
I've been looking around on how to implement a custom NavType for my List but couldn't find anything. Is there a way to do this?
Since I'm pretty new I'm not sure if this is the way to do this either so I'd also appreciate if you could give me an alternative. Would it be better to just pass the id and retrieve the Post again from the Db/API?
follow this article to create a custom nav type https://medium.com/mercadona-tech/type-safety-in-navigation-compose-23c03e3d74a5 remember to pass the map of nav type to the composable function and the navDeepLink parameter, here is an example
composable<Screen.Note>(
typeMap = mapOf(typeOf<LinkedHashSet<LabelUi>>() to navTypeOf<LinkedHashSet<LabelUi>>()),
deepLinks = listOf(
navDeepLink<Screen.Note>(
basePath = DEFAULT_URI,
typeMap = mapOf(typeOf<LinkedHashSet<LabelUi>>() to navTypeOf<LinkedHashSet<LabelUi>>()),
),
)
and here is the navTypeOf implementation:
inline fun <reified T> navTypeOf(
isNullableAllowed: Boolean = false,
json: Json = Json,
) = object : NavType<T>(isNullableAllowed = isNullableAllowed) {
override fun get(bundle: Bundle, key: String): T? =
bundle.getString(key)?.let(json::decodeFromString)
override fun parseValue(value: String): T = json.decodeFromString(Uri.decode(value))
override fun serializeAsValue(value: T): String = Uri.encode(json.encodeToString(value))
override fun put(bundle: Bundle, key: String, value: T) =
bundle.putString(key, json.encodeToString(value))
}
the reason why Uri is used here is mentioned here: https://www.youtube.com/watch?v=qBxaZ071N0c
Remember to pass the type map to the toRoute method
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With