Mah*_*hag 31 android-jetpack-compose jetpack-compose-navigation
从文档中,我可以传递字符串、整数等。但是如何在导航上传递对象呢?
注意:如果我设置参数类型 Parcelable,则应用程序会崩溃并显示java.lang.UnsupportedOperationException: Parcelables don't support default values.
.
composable(
"vendor/details/{vendor}",
arguments = listOf(navArgument("vendor") {
type = NavType.ParcelableType(Vendor::class.java)
})
) {
// ...
}
Run Code Online (Sandbox Code Playgroud)
Mah*_*hag 28
根据导航文档:
注意:通过参数传递复杂的数据结构被认为是反模式。每个目的地应负责根据最少的必要信息(例如项目 ID)加载 UI 数据。这简化了流程重新创建并避免了潜在的数据不一致。
因此,如果可能的话,请避免传递复杂的数据。更多官方详细信息请参见此处。
以下解决方法基于navigation-compose
版本2.7.5
。
我找到了两种传递对象的解决方法。
在这里,我们可以使用对象的 JSON 字符串表示形式来传递对象。
示例代码:
val ROUTE_USER_DETAILS = "user-details?user={user}"
// Pass data (I am using Moshi here)
val user = User(id = 1, name = "John Doe") // User is a data class.
val moshi = Moshi.Builder().build()
val jsonAdapter = moshi.adapter(User::class.java).lenient()
val userJson = jsonAdapter.toJson(user)
navController.navigate(
ROUTE_USER_DETAILS.replace("{user}", userJson)
)
// Receive Data
NavHost {
composable(ROUTE_USER_DETAILS) { backStackEntry ->
val userJson = backStackEntry.arguments?.getString("user")
val moshi = Moshi.Builder().build()
val jsonAdapter = moshi.adapter(User::class.java).lenient()
val userObject = jsonAdapter.fromJson(userJson)
UserDetailsView(userObject) // Here UserDetailsView is a composable.
}
}
// Composable function/view
@Composable
fun UserDetailsView(
user: User?
){
// ...
}
Run Code Online (Sandbox Code Playgroud)
重要提示:如果您的数据有任何 URL 或任何字符串&
等,您可能必须分别使用URLEncoder.encode(jsonString, "utf-8")
和URLDecode.decode(jsonString, "utf-8")
来传递和接收数据。但编码-解码也有一些副作用!就像如果你的字符串有任何+
符号,它会用 aspace
等替换它。
NavBackStackEntry
在这里我们可以使用 传递数据navController.currentBackStackEntry
并使用 接收数据navController.previousBackStackEntry
。
注意:从版本开始,
1.6.0
对 的任何更改都*BackStackEntry.arguments
不会反映在对arguments
. 所以,现在我们必须使用savedStateHandle
. 版本变更详情请参见此处。
示例代码:
val ROUTE_USER_DETAILS = "user-details"
// Pass data
val user = User(id = 1, name = "John Doe") // User is a parcelable data class.
// `arguments` will not work after version 1.6.0.
// navController.currentBackStackEntry?.arguments?.putParcelable("user", user) // old
snavController.currentBackStackEntry?.savedStateHandle?.set("user", user) // new
navController.navigate(ROUTE_USER_DETAILS)
// Receive data
NavHost {
composable(ROUTE_USER_DETAILS) {
// `arguments` will not work after version 1.6.0.
// val userObject = navController.previousBackStackEntry?.arguments?.getParcelable<User>("user") // old
val userObject: User? = navController.previousBackStackEntry?.savedStateHandle?.get("user") // new
UserDetailsView(userObject) // Here UserDetailsView is a composable.
}
}
// Composable function/view
@Composable
fun UserDetailsView(
user: User?
){
// ...
}
Run Code Online (Sandbox Code Playgroud)
重要提示:第二个解决方案不稳定,如果我们在导航时弹出后退堆栈,则该解决方案将不起作用。
归档时间: |
|
查看次数: |
31566 次 |
最近记录: |