如何一起正确使用 viewModel 和组合导航?

How to use viewModel and compose navigation correctly together?

在使用Di的情况下,官网Android的写法如下

// import androidx.hilt.navigation.compose.hiltViewModel

@Composable
fun MyApp() {
    NavHost(navController, startDestination = startRoute) {
        composable("example") { backStackEntry ->
            // Creates a ViewModel from the current BackStackEntry
            // Available in the androidx.hilt:hilt-navigation-compose artifact
            val exampleViewModel = hiltViewModel<ExampleViewModel>()
            ExampleScreen(exampleViewModel)
        }
        /* ... */
    }
}

那么如果ExampleScreen中还有很多其他的@Composable函数,像这样

ExampleScreen() {
  A()
  B()
}
A() {
  TopBar()
  BottomBar()
  ....
}
B() ...

如果A()和它的子函数都需要用到vm里面的东西,那vm的参数一个一个传过去不行吗?因为如果在这些函数中创建了vm,就不是单例了(因为navigation compose会影响到viewModel,每次切换页面时,这些viewModels都会被重新创建为一个新的)。正在百思不得其解的时候,又在官网上看到了这个设计思路:

Pass explicit parameters

大意是我应该把子函数的逻辑代码传递给父函数,例如在 ExampleScreen 中写:

ExampleScreen() {
  val vm = hilt<VM>()
  A(onClick = vm.onClick, ...)
  B(...)
}

所以我的问题是,如果我有很多嵌套函数,我不需要在每个函数中写一个逻辑参数吗?那么如果我想在每个函数中直接创建一个vm,但是又不是单例,怎么办呢?我很困惑

您在顶层注入视图模型是正确的。现在由您决定如何传递它。它们最终只是功能。 您可以在任何地方传递视图模型,仅传递特定成员或不传递任何内容。

做有意义的事,如果行不通就迭代。