Jetpack Compose 使用参数浮动错误进行导航
Jetpack Compose navigate with arguments float error
当我导航到该屏幕时出现此错误,但价格类型为 Float。有人可以帮我解决这个问题吗?
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.invoke(Navigation.kt:48)
at com.example.shop.util.NavigationKt$Navigation.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.invoke(NavHost.kt:142)
at androidx.navigation.compose.NavHostKt$NavHost.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.invoke(NavBackStackEntryProvider.kt:51)
at androidx.navigation.compose.NavBackStackEntryProviderKt$LocalOwnersProvider.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.invoke(NavHost.kt:141)
at androidx.navigation.compose.NavHostKt$NavHost.invoke(NavHost.kt:134)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:116)
at androidx.compose.runtime.internal.ComposableLambdaImpl$invoke.invoke(ComposableLambda.jvm.kt:127)
at androidx.compose.runtime.internal.ComposableLambdaImpl$invoke.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.invoke(Crossfade.kt:75)
at androidx.compose.animation.CrossfadeKt$Crossfade.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.invoke(Unknown Source:13)
at androidx.navigation.compose.NavHostKt$NavHost.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.invoke(Composer.kt:2580)
at androidx.compose.runtime.ComposerImpl$doCompose.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.invoke(Recomposer.kt:447)
at androidx.compose.runtime.Recomposer$runRecomposeAndApplyChanges.invoke(Recomposer.kt:416)
at androidx.compose.ui.platform.AndroidUiFrameClock$withFrameNanos$callback.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.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)
首先,我想说您没有完全按照预期使用导航。
如果对象中的字段数量增加,您会向路由添加新参数吗?这似乎不方便也不可靠。
根据the Navigation documentation:
Caution: Passing complex data structures over arguments is considered an anti-pattern. Each destination should be responsible for loading UI data based on the minimum necessary information, such as item IDs. This simplifies process recreation and avoids potential data inconsistencies.
相反,您可以传递对象的 ID 并将其从存储库中拉出。您可以在维护者制作的 compose 示例中看到这一点。 This is navigation destination where id is taken from the arguments, and this 是通过 id 从存储库中获取对象的屏幕。
以上并不能证明您遇到的行为看起来像是一个错误,因此我建议您将其报告给 compose issue tracker。
同时,您可以切换为传递字符串并将其转换为浮点数:
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()
}
当我导航到该屏幕时出现此错误,但价格类型为 Float。有人可以帮我解决这个问题吗?
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.invoke(Navigation.kt:48)
at com.example.shop.util.NavigationKt$Navigation.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.invoke(NavHost.kt:142)
at androidx.navigation.compose.NavHostKt$NavHost.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.invoke(NavBackStackEntryProvider.kt:51)
at androidx.navigation.compose.NavBackStackEntryProviderKt$LocalOwnersProvider.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.invoke(NavHost.kt:141)
at androidx.navigation.compose.NavHostKt$NavHost.invoke(NavHost.kt:134)
at androidx.compose.runtime.internal.ComposableLambdaImpl.invoke(ComposableLambda.jvm.kt:116)
at androidx.compose.runtime.internal.ComposableLambdaImpl$invoke.invoke(ComposableLambda.jvm.kt:127)
at androidx.compose.runtime.internal.ComposableLambdaImpl$invoke.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.invoke(Crossfade.kt:75)
at androidx.compose.animation.CrossfadeKt$Crossfade.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.invoke(Unknown Source:13)
at androidx.navigation.compose.NavHostKt$NavHost.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.invoke(Composer.kt:2580)
at androidx.compose.runtime.ComposerImpl$doCompose.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.invoke(Recomposer.kt:447)
at androidx.compose.runtime.Recomposer$runRecomposeAndApplyChanges.invoke(Recomposer.kt:416)
at androidx.compose.ui.platform.AndroidUiFrameClock$withFrameNanos$callback.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.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)
首先,我想说您没有完全按照预期使用导航。
如果对象中的字段数量增加,您会向路由添加新参数吗?这似乎不方便也不可靠。
根据the Navigation documentation:
Caution: Passing complex data structures over arguments is considered an anti-pattern. Each destination should be responsible for loading UI data based on the minimum necessary information, such as item IDs. This simplifies process recreation and avoids potential data inconsistencies.
相反,您可以传递对象的 ID 并将其从存储库中拉出。您可以在维护者制作的 compose 示例中看到这一点。 This is navigation destination where id is taken from the arguments, and this 是通过 id 从存储库中获取对象的屏幕。
以上并不能证明您遇到的行为看起来像是一个错误,因此我建议您将其报告给 compose issue tracker。
同时,您可以切换为传递字符串并将其转换为浮点数:
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()
}