英文:
Retrieve parameters in navigation graph scoped viewmodel in Jetpack Compose
问题
与这个问题非常相似,但有一点不同:
https://stackoverflow.com/questions/64955859/scoping-states-in-jetpack-compose
我在导航图中有一个作用域化的 viewModel。我可以检索到它,但我找不到一种优雅的方法来检索参数...
NavHost(navController, ...) {
...
composable(routeWithParameter) {
// (A):在这里,我需要来自路由的 'args' 参数。
// 我目前的解决方案是再次添加参数:
val args = it.arguments?.getString("argumentKey") // 从路由中检索 'args'
val state = it.getRememberedParent(navController) // 获取父级
state.arguments?.putString("argumentKey", args ) // 再次在父级状态中添加 'args'
val viewModel = hiltViewModel<TViewModel>(state)
Log.d("MISC", "id =${System.identityHashCode(viewModel)}") // 与 (B) 相同的实例
...
}
composable(route) {
// (B):
val viewModel = hiltViewModel<TViewModel>(it.getRememberedParent(navController))
Log.d("MISC", "id =${System.identityHashCode(viewModel)}") // 与 (A) 相同的实例
...
}
...
}
@Composable
fun NavBackStackEntry.getRememberedParent(navController: NavHostController): NavBackStackEntry {
val parentId = this.destination.parent!!.id
return remember(this) { navController.getBackStackEntry(parentId) }
}
在视图模型中,参数是使用 SavedStateHandle 检索的,如下所示:
@HiltViewModel
class EditFarmViewModel @Inject constructor(
state: SavedStateHandle,
) : ViewModel() {
private val _args = checkNotNull(state.get<String>("argumentKey"))
为了在 (A) 和 (B) 中获得相同的 viewModel 实例,我不能简单地使用 hiltViewModel<TViewModel>()
来构建 viewModel (A),因为这会导致为 (B) 创建另一个实例...
我没有在文档中找到任何窍门(https://developer.android.com/jetpack/compose/libraries#hilt)
=> 如何在 (A) 中检索路由参数而不重新插入它们?
OR
=> 如何在 (A) 中查找父级而不使用 getBackStackEntry(并且使用初始路由参数)来获取相同的作用域化实例?
英文:
Very similar to this issue but with a slight difference:
https://stackoverflow.com/questions/64955859/scoping-states-in-jetpack-compose
I have a scoped viewModel in a navigation graph. I can retrieve it but I do not find an elegant way of retrieving parameters ...
NavHost(navController, ...) {
...
composable(routeWithParameter) {
// (A): here, I need an 'args' parameter from route.
// My current solution is to 'add again' the parameter:
val args = it.arguments?.getString("argumentKey") // retrieve 'args' from route
val state = it.getRememberedParent(navController) // get parent
state.arguments?.putString("argumentKey", args ) // add again the 'args' in parent state
val viewModel = hiltViewModel<TViewModel>(state)
Log.d("MISC", "id =${System.identityHashCode(viewModel)}") // same instance as (B)
...
}
composable(route) {
// (B):
val viewModel = hiltViewModel<TViewModel>(it.getRememberedParent(navController))
Log.d("MISC", "id =${System.identityHashCode(viewModel)}") //same instance as (A)
...
}
...
}
@Composable
fun NavBackStackEntry.getRememberedParent(navController: NavHostController): NavBackStackEntry {
val parentId = this.destination.parent!!.id
return remember(this) { navController.getBackStackEntry(parentId) }
}
In the view model, parameters are retrieved using SavedStateHandle like this:
@HiltViewModel
class EditFarmViewModel @Inject constructor(
state: SavedStateHandle,
) : ViewModel() {
private val _args = checkNotNull(state.get<String>("argumentKey"))
In order to get the same viewModel instance in (A) and (B), I cannot build viewModel (A) by simply using hiltViewModel<TViewModel>() without state as it leads to another instance beeing created for (B)...
I haven't found any trick in the doc (https://developer.android.com/jetpack/compose/libraries#hilt)
=> How to retrieve route parameters for (A) without re-inserting them?
OR
=> How to get the same scoped instance without using the getBackStackEntry to find parent in (A) (and so, use the initial route parameters)?
答案1
得分: 0
事实上,错误是我必须创建一个嵌套的图形来访问共享范围的视图模型可组合,并将导航参数传递给嵌套图形的根。
像这样:
NavHost(navController, ...) {
// => 这里是嵌套导航图,是唯一带有参数的导航图
navigation(route = routeWithParameters, startDestination = nestedrouteA
){
composable(nestedrouteA) {
val state = it.getRememberedParent(navController) // 获取父级
val viewModel = hiltViewModel<TViewModel>(state)
Log.d("MISC", "id =${System.identityHashCode(viewModel)}") // 与(B)相同的实例
...
}
composable(nestedrouteB) {
// (B):
val viewModel = hiltViewModel<TViewModel>(it.getRememberedParent(navController))
Log.d("MISC", "id =${System.identityHashCode(viewModel)}") // 与(A)相同的实例
...
}
}
...
}
英文:
In fact, the error was I had to create a nested graph to access shared scope viewmodel composable and give the navigation parameter to the nested graph root.
like this:
NavHost(navController, ...) {
// => NESTED Navigation graph HERE that is the only one with arguments
navigation(route = routeWithParameters, startDestination = nestedrouteA
){
composable(nestedrouteA) {
val state = it.getRememberedParent(navController) // get parent
val viewModel = hiltViewModel<TViewModel>(state)
Log.d("MISC", "id =${System.identityHashCode(viewModel)}") // same instance as (B)
...
}
composable(nestedrouteB) {
// (B):
val viewModel = hiltViewModel<TViewModel>(it.getRememberedParent(navController))
Log.d("MISC", "id =${System.identityHashCode(viewModel)}") //same instance as (A)
...
}
}
...
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论