Jetpack Создает навигацию с ошибками с плавающей точкой аргументов

#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()
}