#android #android-jetpack #android-jetpack-compose #android-jetpack-navigation
Вопрос:
Когда я перехожу на этот экран, я получаю эту ошибку, но тип цены-Плавающий. Может кто-нибудь помочь мне с этой проблемой, пожалуйста?
data class Product(
val imgUrl: String = "",
val title: String = "",
val price: Float = 0f,
val description: String = "",
)
composable(
route = Screen.InspectProduct.route "/{description}/{title}/{price}/{imgUrl}",
arguments = listOf(
navArgument(name = "title") { NavType.StringType },
navArgument(name = "description") { NavType.StringType },
navArgument(name = "price") { NavType.FloatType },
navArgument(name = "imgUrl") { NavType.StringType },
)
) { backStackEntry ->
Log.d(TAG, backStackEntry.arguments?.getFloat( "price")!!.toString())
InspectProduct1(
navController = navController,
Product(
title = backStackEntry.arguments?.getString("title")!!,
description = backStackEntry.arguments?.getString("description")!!,
imgUrl = backStackEntry.arguments?.getString("imgUrl")!!,
price = backStackEntry.arguments?.getFloat( "price")!!
)
)
}
navController.navigate(
route = Screen.InspectProduct.route "/${product.description}/${product.title}/${product.price}/${urlEncoder(product.imgUrl)}"
)
2021-09-03 01:13:56.208 10933-10933/com.example.shop D/ContentValues: 0.0
2021-09-03 01:13:56.209 10933-10933/com.example.shop W/Bundle: Key price expected Float but value was a java.lang.String. The default value 0.0 was returned.
2021-09-03 01:13:56.209 10933-10933/com.example.shop W/Bundle: Attempt to cast generated internal exception:
java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Float
at android.os.BaseBundle.getFloat(BaseBundle.java:1145)
at android.os.Bundle.getFloat(Bundle.java:891)
at android.os.BaseBundle.getFloat(BaseBundle.java:1127)
at android.os.Bundle.getFloat(Bundle.java:878)
at com.example.shop.util.NavigationKt$Navigation$1$9.invoke(Navigation.kt:48)
at com.example.shop.util.NavigationKt$Navigation$1$9.invoke(Navigation.kt:38)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:116)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
at androidx.navigation.compose.NavHostKt$NavHost$3$1.invoke(NavHost.kt:142)
at androidx.navigation.compose.NavHostKt$NavHost$3$1.invoke(NavHost.kt:141)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:215)
at androidx.compose.runtime.saveable.SaveableStateHolderImpl.SaveableStateProvider(SaveableStateHolder.kt:84)
at androidx.navigation.compose.NavBackStackEntryProviderKt.SaveableStateProvider(NavBackStackEntryProvider.kt:59)
at androidx.navigation.compose.NavBackStackEntryProviderKt.access$SaveableStateProvider(NavBackStackEntryProvider.kt:1)
at androidx.navigation.compose.NavBackStackEntryProviderKt$LocalOwnersProvider$1.invoke(NavBackStackEntryProvider.kt:51)
at androidx.navigation.compose.NavBackStackEntryProviderKt$LocalOwnersProvider$1.invoke(NavBackStackEntryProvider.kt:50)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
at androidx.compose.runtime.CompositionLocalKt.CompositionLocalProvider(CompositionLocal.kt:215)
at androidx.navigation.compose.NavBackStackEntryProviderKt.LocalOwnersProvider(NavBackStackEntryProvider.kt:46)
at androidx.navigation.compose.NavHostKt$NavHost$3.invoke(NavHost.kt:141)
at androidx.navigation.compose.NavHostKt$NavHost$3.invoke(NavHost.kt:134)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:116)
at androidx.compose.runtime.internal.ComposableLambdaImpl$invoke$1.invoke(ComposableLambda.jvm.kt:127)
at androidx.compose.runtime.internal.ComposableLambdaImpl$invoke$1.invoke(ComposableLambda.jvm.kt:127)
at androidx.compose.runtime.RecomposeScopeImpl.compose(RecomposeScopeImpl.kt:140)
at androidx.compose.runtime.ComposerImpl.recomposeToGroupEnd(Composer.kt:2156)
at androidx.compose.runtime.ComposerImpl.skipToGroupEnd(Composer.kt:2422)
at androidx.compose.animation.CrossfadeKt$Crossfade$1$1.invoke(Crossfade.kt:75)
at androidx.compose.animation.CrossfadeKt$Crossfade$1$1.invoke(Crossfade.kt:69)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:107)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:34)
at androidx.compose.animation.CrossfadeKt.Crossfade(Crossfade.kt:86)
at androidx.navigation.compose.NavHostKt.NavHost(NavHost.kt:134)
at androidx.navigation.compose.NavHostKt$NavHost$4.invoke(Unknown Source:13)
at androidx.navigation.compose.NavHostKt$NavHost$4.invoke(Unknown Source:10)
at androidx.compose.runtime.RecomposeScopeImpl.compose(RecomposeScopeImpl.kt:140)
at androidx.compose.runtime.ComposerImpl.recomposeToGroupEnd(Composer.kt:2156)
at androidx.compose.runtime.ComposerImpl.skipCurrentGroup(Composer.kt:2399)
at androidx.compose.runtime.ComposerImpl$doCompose$2$5.invoke(Composer.kt:2580)
at androidx.compose.runtime.ComposerImpl$doCompose$2$5.invoke(Composer.kt:2573)
at androidx.compose.runtime.SnapshotStateKt.observeDerivedStateRecalculations(SnapshotState.kt:540)
at androidx.compose.runtime.ComposerImpl.doCompose(Composer.kt:2566)
2021-09-03 01:13:56.209 10933-10933/com.example.shop W/Bundle: at androidx.compose.runtime.ComposerImpl.recompose$runtime_release(Composer.kt:2542)
at androidx.compose.runtime.CompositionImpl.recompose(Composition.kt:613)
at androidx.compose.runtime.Recomposer.performRecompose(Recomposer.kt:764)
at androidx.compose.runtime.Recomposer.access$performRecompose(Recomposer.kt:103)
at androidx.compose.runtime.Recomposer$runRecomposeAndApplyChanges$2$2.invoke(Recomposer.kt:447)
at androidx.compose.runtime.Recomposer$runRecomposeAndApplyChanges$2$2.invoke(Recomposer.kt:416)
at androidx.compose.ui.platform.AndroidUiFrameClock$withFrameNanos$2$callback$1.doFrame(AndroidUiFrameClock.android.kt:34)
at androidx.compose.ui.platform.AndroidUiDispatcher.performFrameDispatch(AndroidUiDispatcher.android.kt:109)
at androidx.compose.ui.platform.AndroidUiDispatcher.access$performFrameDispatch(AndroidUiDispatcher.android.kt:41)
at androidx.compose.ui.platform.AndroidUiDispatcher$dispatchCallback$1.doFrame(AndroidUiDispatcher.android.kt:69)
at android.view.Choreographer$CallbackRecord.run(Choreographer.java:970)
at android.view.Choreographer.doCallbacks(Choreographer.java:796)
at android.view.Choreographer.doFrame(Choreographer.java:727)
at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:957)
at android.os.Handler.handleCallback(Handler.java:938)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:223)
at android.app.ActivityThread.main(ActivityThread.java:7656)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
Комментарии:
1. Передайте цену в виде строки вместо fload. В пункте назначения преобразуйте значение с плавающей точкой в строку. Посмотрим, сработает ли это.
Ответ №1:
Прежде всего, я хотел бы сказать, что вы используете навигацию не совсем так, как она задумана.
Если количество полей в вашем объекте увеличится, вы добавите новые параметры в маршрут? Это не кажется удобным или надежным.
В соответствии с навигационной документацией:
Внимание: Передача сложных структур данных по аргументам считается анти-шаблоном. Каждое место назначения должно отвечать за загрузку данных пользовательского интерфейса на основе минимально необходимой информации, такой как идентификаторы элементов. Это упрощает воссоздание процесса и позволяет избежать возможных несоответствий данных.
Вместо этого вы можете передать идентификатор объекта и извлечь его из репозитория. Вы можете увидеть это в образцах, сделанных сопровождающими. Это пункт назначения навигации, где идентификатор берется из аргументов, и это экран, на котором объект берется из репозитория по идентификатору.
Вышесказанное не отменяет того факта, что поведение, с которым вы столкнулись, похоже на ошибку, поэтому я предлагаю вам сообщить об этом в службу отслеживания ошибок.
Тем временем вы можете переключиться на передачу строки и преобразование ее в float:
composable(
route = Screen.InspectProduct.route "/{description}/{title}/{price}/{imgUrl}",
arguments = listOf(
navArgument(name = "title") { NavType.StringType },
navArgument(name = "description") { NavType.StringType },
navArgument(name = "price") { NavType.StringType },
navArgument(name = "imgUrl") { NavType.StringType },
)
) { backStackEntry ->
val product = Product(
title = backStackEntry.arguments?.getString("title")!!,
description = backStackEntry.arguments?.getString("description")!!,
imgUrl = backStackEntry.arguments?.getString("imgUrl")!!,
price = backStackEntry.arguments?.getString("price")!!.toFloat()
).toString()
}