android - Jetpack Compose 中的作用域状态
问题描述
使用 Compose,可以通过以下方式实现“每屏幕状态”:
NavHost(navController, startDestination = startRoute) {
...
composable(route) {
...
val perScreenViewModel = viewModel() // This will be different from
}
composable(route) {
...
val perScreenViewModel = viewModel() // this instance
}
...
}
“应用程序状态”可以通过以下方式实现:
val appStateViewModel = viewModel()
NavHost(navController, startDestination = startRoute) {
...
}
但是“作用域状态”呢?我们如何在 Compose 中实现它?
解决方案
这正是导航图范围视图模型的用途。
这包括两个步骤:
查找
NavBackStackEntry
与要将 ViewModel 范围限定为的图关联的将其传递给
viewModel()
.
对于第 1 部分),您有两个选择。如果您知道导航图的路线(通常您应该知道),您可以getBackStackEntry
直接使用:
// Note that you must always use remember with getBackStackEntry
// as this ensures that the graph is always available, even while
// your destination is animated out after a popBackStack()
val navigationGraphEntry = remember {
navController.getBackStackEntry("graph_route")
}
val navigationGraphScopedViewModel = viewModel(navigationGraphEntry)
但是,如果您想要更通用的东西,您可以使用目标本身中的信息检索回栈条目 - 它parent
:
fun NavBackStackEntry.rememberParentEntry(): NavBackStackEntry {
// First, get the parent of the current destination
// This always exists since every destination in your graph has a parent
val parentId = navBackStackEntry.destination.parent!!.id
// Now get the NavBackStackEntry associated with the parent
// making sure to remember it
return remember {
navController.getBackStackEntry(parentId)
}
}
这使您可以编写如下内容:
val parentEntry = it.rememberParentEntry()
val navigationGraphScopedViewModel = viewModel(parentEntry)
虽然parent
目的地将等于简单导航图的根图,但当您使用嵌套导航时,父级是图的中间层之一:
NavHost(navController, startDestination = startRoute) {
...
navigation(startDestination = nestedStartRoute, route = nestedRoute) {
composable(route) {
// This instance will be the same
val parentViewModel: YourViewModel = viewModel(it.rememberParentEntry())
}
composable(route) {
// As this instance
val parentViewModel: YourViewModel = viewModel(it.rememberParentEntry())
}
}
navigation(startDestination = nestedStartRoute, route = secondNestedRoute) {
composable(route) {
// But this instance is different
val parentViewModel: YourViewModel = viewModel(it.rememberParentEntry())
}
}
composable(route) {
// This is also different (the parent is the root graph)
// but the root graph has the same scope as the whole NavHost
// so this isn't particularly helpful
val parentViewModel: YourViewModel = viewModel(it.rememberParentEntry())
}
...
}
请注意,您不仅限于直接父级:每个父级导航图都可用于提供更大的范围。
推荐阅读
- powershell - 获取其他 Windows 帐户的存在状态?
- elasticsearch - 我可以过滤弹性数组吗?
- java - Java JPMS 和包含库的 jars
- jdbc - 在服务器中运行查询时使用 Snowflake JDBC 获取行
- reactjs - 将 React Hook 传递给功能组件
- c# - 从逗号分隔的字符串C#中删除某些字符串
- instagram - 有什么方法可以创建从有机 instagram 故事(不是广告)到我的移动应用程序中特定内容的深层链接?
- javascript - 使用 createProxyMiddleware 重写动态路径并创建反应应用程序
- lua - Roblox 上的大亨游戏
- sql-server - SQL Server 表的主键上的 int 值用完