使用撰写导航传递 Parcelable 参数 [英] Pass Parcelable argument with compose navigation
问题描述
我想使用组合导航将可打包对象 (BluetoothDevice
) 传递给可组合对象.
I want to pass a parcelable object (BluetoothDevice
) to a composable using compose navigation.
传递原始类型很容易:
composable(
"profile/{userId}",
arguments = listOf(navArgument("userId") { type = NavType.StringType })
) {...}
navController.navigate("profile/user1234")
但是我不能在路由中传递一个parcelable对象,除非我可以将它序列化为一个字符串.
But I can't pass a parcelable object in the route unless I can serialize it to a string.
composable(
"deviceDetails/{device}",
arguments = listOf(navArgument("device") { type = NavType.ParcelableType(BluetoothDevice::class.java) })
) {...}
val device: BluetoothDevice = ...
navController.navigate("deviceDetails/$device")
上面的代码显然不起作用,因为它只是隐式调用了toString()
.
The code above obviously doesn't work because it just implicitly calls toString()
.
有没有办法将 Parcelable
序列化为 String
以便我可以在路由中传递它或将导航参数作为具有除此之外的函数的对象传递navigate(route: String)
?
Is there a way to either serialize a Parcelable
to a String
so I can pass it in the route or pass the navigation argument as an object with a function other than navigate(route: String)
?
推荐答案
更新为 Compose 1.0.3 和导航 2.4.0-alpha10
Updated to Compose 1.0.3 and Navigation 2.4.0-alpha10
似乎不再支持以前的解决方案.现在您需要创建一个自定义的NavType
.
Seems like previous solution is not supported anymore. Now you need to create a custom NavType
.
假设您有一个类:
@Parcelize
data class Device(val id: String, val name: String) : Parcelable
然后你需要定义一个NavType
class AssetParamType : NavType<Device>(isNullableAllowed = false) {
override fun get(bundle: Bundle, key: String): Device? {
return bundle.getParcelable(key)
}
override fun parseValue(value: String): Device {
return Gson().fromJson(value, Device::class.java)
}
override fun put(bundle: Bundle, key: String, value: Device) {
bundle.putParcelable(key, value)
}
}
请注意,我使用 Gson
将对象转换为 JSON 字符串.但是您可以使用您喜欢的转换器...
Notice that I'm using Gson
to convert the object to a JSON string. But you can use the conversor that you prefer...
然后像这样声明你的可组合:
Then declare your composable like this:
NavHost(...) {
composable("home") {
Home(
onClick = {
val device = Device("1", "My device")
val json = Uri.encode(Gson().toJson(device))
navController.navigate("details/$json")
}
)
}
composable(
"details/{device}",
arguments = listOf(
navArgument("device") {
type = AssetParamType()
}
)
) {
val device = it.arguments?.getParcelable<Device>("device")
Details(device)
}
}
更新为beta-07
基本上你可以做到以下几点:
Basically you can do the following:
// In the source screen...
navController.currentBackStackEntry?.arguments =
Bundle().apply {
putParcelable("bt_device", device)
}
navController.navigate("deviceDetails")
在详细信息屏幕中...
And in the details screen...
val device = navController.previousBackStackEntry
?.arguments?.getParcelable<BluetoothDevice>("bt_device")
这篇关于使用撰写导航传递 Parcelable 参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!