Issue
I'm using Jetpack Compose Navigation to pass a Health instance to another composable. The below code shows my health class and my Destination.
Health.kt:
data class Health(
val height: Int,
val weight: Int,
val age: Int,
val gender: Gender
) : Serializable
enum class Gender: Serializable { Male, Female }
NavDestination.kt
composable(
route = "result/{health}",
arguments = listOf(
navArgument("health") {
type =
NavType.SerializableType(Health::class.java)
}
)
) { backStackEntry ->
val health = (backStackEntry.arguments?.getSerializable("health") as? Health) ?: return@composable
ResultScreen(navActions = navActions, health = health)
}
NavActions.kt
val navigateToResultScreen = { health: Health ->
navController.navigate("result/{$health}")
}
However, I'm getting this error according to the logcat. Any assistance would be highly appreciated.
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.octagon_technologies.bmicalculator, PID: 20788
java.lang.UnsupportedOperationException: Serializables don't support default values.
at androidx.navigation.NavType$SerializableType.parseValue(NavType.java:838)
at androidx.navigation.NavType$SerializableType.parseValue(NavType.java:791)
at androidx.navigation.NavType.parseAndPut(NavType.java:96)
at androidx.navigation.NavDeepLink.parseArgument(NavDeepLink.java:299)
at androidx.navigation.NavDeepLink.getMatchingArguments(NavDeepLink.java:260)
at androidx.navigation.NavDestination.matchDeepLink(NavDestination.java:474)
at androidx.navigation.NavGraph.matchDeepLink(NavGraph.java:79)
at androidx.navigation.NavController.navigate(NavController.java:1034)
at androidx.navigation.NavController.navigate(NavController.java:1017)
at androidx.navigation.compose.NavHostControllerKt.navigate(NavHostController.kt:107)
at androidx.navigation.compose.NavHostControllerKt.navigate$default(NavHostController.kt:106)
at com.octagon_technologies.bmicalculator.ui.navigation.NavActions$navigateToResultScreen$1.invoke(NavActions.kt:9)
at com.octagon_technologies.bmicalculator.ui.navigation.NavActions$navigateToResultScreen$1.invoke(NavActions.kt:8)
at com.octagon_technologies.bmicalculator.ui.screens.home.HomeScreenKt$HomeScreen$1$6.invoke(HomeScreen.kt:122)
at com.octagon_technologies.bmicalculator.ui.screens.home.HomeScreenKt$HomeScreen$1$6.invoke(HomeScreen.kt:120)
at com.octagon_technologies.bmicalculator.ui.components.home.CalculateBtnKt$CalculateButton$1$1$1.invoke(CalculateBtn.kt:29)
at com.octagon_technologies.bmicalculator.ui.components.home.CalculateBtnKt$CalculateButton$1$1$1.invoke(CalculateBtn.kt:29)
Solution
Why this couldn't work: https://issuetracker.google.com/issues/148523779
"Serializable
and Parcelable
have no consistent API surface that would allow automatic parsing of a string into your custom class instance. That's why parseValue
throws an UnsupportedOperationException
."
It's expected that you'll only pass ids in this deep links, not full objects
Workaround:
composable(
route = "result",
arguments = listOf(
navArgument("health") {
type =
NavType.SerializableType(Health::class.java)
}
)
) {
val health = (navController.previousBackStackEntry.arguments?.getSerializable("health") as? Health) ?: return@composable
ResultScreen(navActions = navActions, health = health)
}
Navigate like this:
navController.currentBackStackEntry
?.arguments?.putSerializable("health", health)
navController.navigate("result")
Answered By - Phil Dukhov
Answer Checked By - Marie Seifert (JavaFixing Admin)