@SuppressLint("DiscouragedApi")
@Composable
fun PuzzleScreen(
navController: NavHostController,
sharedViewModel: SharedViewModel,
letter: String,
puzzleViewModel: PuzzleViewModel = hiltViewModel(),
) {
val state by puzzleViewModel.viewState.collectAsState()
/..../
}
问题是,当我从 PuzzleScreen 转到第二个,然后返回到 PuzzleScreen 时。然后系统重新更新 PuzzleScreen 屏幕。我需要确保状态被保存并被记住。怎么办?
如果不困难,请分享解释如何执行此操作的网站或在 GitHub 上使用它
如果您使用
hiltViewModel()
,则 Hilt 创建的 ViewModel 实例默认作用域为 NavGraphEntry
。这意味着一旦从后台堆栈中删除该目标,ViewModel 就会被清除。重新访问目的地后,将创建一个新实例。
首先,确保正确处理导航。如果您想导航到后续屏幕而不从后退堆栈中清除当前目的地,请使用
navController.navigate(Destination.SecondDestination.route)
然后要返回到后退堆栈上的上一个目的地,请执行
navController.popBackStack()
这样,ViewModel 状态就不会丢失。
作为替代方案,您可以手动传递 ViewModel 的作用域范围的
NavGraphEntry
。如果您传递根 Composable 的 NavGraphEntry
,则 ViewModel 将可用,直到应用程序关闭。这必须发生在您的可组合项之外,例如在您的 NavHost 中。代码如下所示:
composable(Destination.FirstDestination.route) { navBackStackEntry ->
val parentEntry = remember(navBackStackEntry) {
navController.getBackStackEntry(Destination.RootDestination.route)
}
val puzzleViewModel = hiltViewModel<PuzzleViewModel>(parentEntry)
PuzzleScreem(
// ...
puzzleViewModel = puzzleViewModel
})
}
请注意,您当前观察到的行为与重组无关。每个定义的 ViewModel 在重组期间保留其状态。您的问题与重组无关,而是与导航有关。