android - 将条目插入 Room 数据库时,ViewModelScope 可能会被取消

标签 android kotlin android-jetpack-compose android-viewmodel koin

我正在构建一个分数跟踪应用程序,并且我有一个屏幕,您可以在其中将新玩家添加到游戏中。这是一个简单的屏幕,可让用户指定玩家的名称和颜色。该屏幕有自己的 ViewModel,我通过使用 Koin 框架将其注入(inject)到屏幕的可组合函数中,如下所示:

fun NewPlayerScreen(
    viewModel: NewPlayerScreenViewModel = getViewModel(),
    navController: NavHostController,
    modifier: Modifier = Modifier
)

这可以确保只要屏幕在屏幕上可见,ViewModel 就一直存在。当用户单击屏幕上的“保存”按钮时,新玩家将被插入到房间数据库中。然而,我的问题是,插入数据库是由 NewPlayerScreenViewModel 处理的。一旦用户提交新的播放器,屏幕就会退出,ViewModel 就会被销毁,这也意味着它的 CoroutineScope 会被取消,这意味着我正在进行的数据库操作(即将播放器插入数据库)可能无法正常完成。

我知道有一个解决方案;我可以像这样将事件从函数中提升出来:

fun NewPlayerScreen(
    viewModel: NewPlayerScreenViewModel = getViewModel(),
    navController: NavHostController,
    onPlayerSave: (newPlayer: Player) -> Unit,
    modifier: Modifier = Modifier
)

但是,这意味着我现在必须在我的 MainScreenViewModel 中的另一个 ViewModel 中处理对数据库的插入,因为我的 的父级NewPlayerScreen() 可组合项是 MainScreen()。我不喜欢这种方法,因为我希望我的屏幕有自己的 ViewModel 来自行处理数据库操作。还有其他选择吗?或者这是处理这种情况的正确方法吗?

最佳答案

您可以:

  • 等待插入发生,然后再导航到下一个屏幕

您可以通过将插入函数设置为 suspend 函数,创建 val coroutineScope = RememberCoroutineScope() 来实现此目的,然后在保存按钮的 onClick 回调上执行以下操作:

coroutineScope.launch {
    viewModel.insertPlayer()
    navigate()
}

这样做可以保证操作将按顺序发生,但缺点是用户必须等到添加播放器后才能导航到下一个屏幕。

  • 使用 WorkManager 安排工作的 OneTimeWorkRequest

关于android - 将条目插入 Room 数据库时,ViewModelScope 可能会被取消,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73209284/

相关文章:

java - 如何从kotlin中的列表中删除一些元素

android - 修饰符工厂函数不应标记为@Composable

android-jetpack-compose - Firebase 应用程序中 Compose 的仪器测试

android - 如何在android中创建多个本地通知

android - 在 NestedScrollView 中使用 RecyclerView 进行分页

javascript - Windows 上是否有适合 React Native 的良好 IDE?

android - 如何使用 Jetpack Compose Navigation 处理弹出多个屏幕

android - Android中如何获取方向(如北、西)

android - 如何使用在函数内设置的匿名监听器测试类?

spring-boot - Kotlin Gradle 无法找到或加载主类