我有一个对应ViewModel的屏幕.此屏幕是要填写的表格,然后记录在Room数据库中.

每次插入后,还必须相应地更新其他一些表.

我的存储库中有以下函数:

 suspend fun writeTransactionToDatabase(transaction: Transaction) {
        db.withTransaction { // <-- "magic" solution
            transactionDao.insert(transaction)
            updateCategoryAndValue(transaction)
            updateBalance(transaction)
        }
    }

其中,updateCategoryAndValueupdateBalance都是suspend个函数. 我从我的视图模型中调用此函数,并立即导航离开.我的理解是,这意味着视图模型已被销毁. 由于我是这样调用此方法的:

 viewModelScope.launch {
     repository.writeTransactionToDatabase(transaction)
 }

我假设这意味着当视图模型被 destruct 时,函数被 destruct .然而,通过添加withTransaction,这个错误似乎被修复了.

我想知道取消在这种情况下是如何工作的,如果房间已经开始并且withTransaction使其成为原子的,那么房间是否继续当前的事务,所以它现在以某种方式结束了?

我在调试器中运行了这个函数,如果没有它,该函数似乎在第三个被调用的函数体(即updateBalance())中途被取消.当我添加withTransaction时,用户界面没有显示,该功能似乎一直持续到终止.

有人能解释一下这是怎么回事吗?先谢谢你.

推荐答案

加上@MikeT的回答,我认为这种行为的根本原因在于RoomDatabase.startTransactionCoroutine():

suspendCancellableCoroutine { continuation ->
    try {
        transactionExecutor.execute {
            try {
                ...
            } catch (ex: Throwable) {
                // If anything goes wrong, propagate exception to the calling coroutine.
                continuation.cancel(ex)
            }
        }
    } catch (ex: RejectedExecutionException) {
        // Couldn't acquire a thread, cancel coroutine.
        continuation.cancel(
            IllegalStateException(
                "Unable to acquire a thread to perform the database transaction.", ex
            )
        )
    }
}

这段代码对我来说很奇怪.他们将执行安排在自己的执行者之上.他们正确地将失败从执行者传递给协程,但不会反过来做--他们忽略协程取消.

在常规执行期间,它会正确地等待操作完成,然后才会从挂起函数返回.但在取消的情况下,函数立即返回,而操作仍在后台运行.因此,取消并不会取消操作,它只是分离等待操作.

我不知道这是故意的还是某种漏洞,但至少对我来说,这种行为非常令人困惑.首先,取消不会取消.其次,行为不一致:有时它会等待操作完成,有时会在后台运行.

Kotlin相关问答推荐

如何确保Kotlin子类已完成初始化?

如何修改muableStateMapOf的值?

如何检测一个值是否是Kotlin中的枚举实例?

为什么在jacksonObjectMapper上将DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES设置为false无效?

将一个列表元素分组为多个组(indexBy)

每个 Kotlin 版本的默认 Kotlin 语言版本是什么?

具有泛型类型的 Kotlin 密封接口不会为其子类型推断约束

如何使用子变量在 Kotlin 中初始化父级

使用 Compose for Desktop Bundle 文件

Kotlin - 创建指定长度的随机整数的 ArrayList?

在 SplashActivity 中显示的 Firebase 应用内消息.如何在 MainActivity 中显示它?

如何为 material.Slider 视图创建绑定适配器?

如何从 Firestore 查询中排除元素?

面临一些未知问题一些后端jvm内部错误

当被Spring代理类访问时,Kotlin实例变量为null

Android 上的 Kotlin:将map到list

在Kotlin中使用@Service时引发异常

(kotlin的Moshi)@Json vs@field:Json

如何让数据类在Kotlin中实现接口/扩展超类属性?

Kotlin Flow 收集后无法执行代码