Jetpack Compose 中的作用域状态 [英] Scoping States in Jetpack Compose

查看:55
本文介绍了Jetpack Compose 中的作用域状态的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在所有应用程序中,总会有这三种状态范围:

In all applications there will always be this three scopes of state:

使用 Compose,每个屏幕状态"可以通过以下方式实现:

With Compose, a "Per Screen State" could be achieved by:

NavHost(navController, startDestination = startRoute) {
    ...
    composable(route) {
       ...
       val perScreenViewModel = viewModel()  // This will be different from
    }
    composable(route) {
       ...
       val perScreenViewModel = viewModel()  // this instance
    }
    ...
}

应用状态"可以通过以下方式实现:

The "App State" could be achieved by:

val appStateViewModel = viewModel()
NavHost(navController, startDestination = startRoute) {
    ...
}

但是对于Scoped State"呢?我们如何在 Compose 中实现它?

But how about for "Scoped State"? How could we achieve it in Compose?

推荐答案

这正是 导航图范围视图模型用于.

这包括两个步骤:

  1. 找到与您要将 ViewModel 限定为范围的图表相关联的 NavBackStackEntry

将其传递给 viewModel().

对于第 1) 部分,您有两个选择.如果你知道导航图的路线(通常你应该知道),你可以直接使用 getBackStackEntry :

For part 1), you have two options. If you know the route of the navigation graph (which, in general, you should), you can use getBackStackEntry directly:

// 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:

However, if you want something more generic, you can retrieve the back stack entry by using the information in the destination itself - its 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()

虽然 parent 目标将等于简单导航图的根图,但当您使用 嵌套导航,父级是图形的中间层之一:

While the parent destination will be equal to the root graph for a simple navigation graph, when you use nested navigation, the parent is one of the intermediate layers of your graph:

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())
  }
  ...
}

请注意,您不仅限于直接父级:每个父级导航图都可用于提供更大的范围.

Note that you are not limited to only the direct parent: every parent navigation graph can be used to provide larger scopes.

这篇关于Jetpack Compose 中的作用域状态的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆