Horizo​​ntalPager 中的每个可组合页面有一个 ViewModel

v.d*_*v.d 7 android android-jetpack-compose

我正在将我的项目从视图系统转换为撰写。在旧视图系统中的应用程序页面之一中,我有一个带有一个 viewPager 的片段,它只是使同一片段的一些页面具有不同的数据来显示。虽然每个片段都有自己的生命周期,但每个片段可以有多个独立的 viewModel。据我所知,在 Compose 中,viewModel 生命周期附加到导航图,因此每次我尝试访问 viewModel 时,它只会返回在第一次调用中创建的相同 viewModel 对象。如何在撰写中实现相同的视图系统行为?

这是我的应用程序现在正在执行的操作的简化版本

@Composable
fun MainScreen(mainViewModel: MainViewModel = hiltViewModel()) {
    val pages = mainViewModel.pages.collectAsState()
    val pagerState = rememberPagerState(pageCount = pages.size)
    HorizontalPager(state = pagerState) {
        ChildScreen()
    }
}

@Composable
fun ChildScreen(childViewModel:ChildViewModel = hiltViewModel()){
    
}
Run Code Online (Sandbox Code Playgroud)

这里childViewModel始终是所有页面的一个对象

Nha*_*tVM 4

正如 @Pavlov Svyatoslav 评论的那样,首先您需要一个新版本的导航。目前是 1.1.0-alpha01

implementation("androidx.hilt:hilt-navigation-compose:1.1.0-alpha01")
Run Code Online (Sandbox Code Playgroud)

然后您可以为 hiltViewModel() 函数添加一个键,如下所示:

@Composable
fun ChildScreen(childViewModel:ChildViewModel = hiltViewModel(key = "what_key")){
    
}
Run Code Online (Sandbox Code Playgroud)

这里的问题是我们应该使用什么键?如果我们使用随机密钥,也许系统总是会为同一个 ChildScreen 创建一个新的 ViewModel。正确的?所以我的解决方案是让 MainScreen 创建一个 ChildViewModel 的实例,然后将其传递给 ChildScreen:

  @Composable
    fun MainScreen(mainViewModel: MainViewModel = hiltViewModel()) {
        val pages = mainViewModel.pages.collectAsState()
        val pagerState = rememberPagerState(pageCount = pages.size)
        HorizontalPager(state = pagerState) {index ->
val childViewModel  = hiltViewModel(key = index.toString) // or any key in here
            ChildScreen(childViewModel)
        }
    }
    
    @Composable
    fun ChildScreen(childViewModel:ChildViewModel){
        
    }
Run Code Online (Sandbox Code Playgroud)