You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android Kotlin中如何取消失败的Realm写事务以开启新事务?

解决Realm写事务残留问题

问题原因

当主键冲突抛出异常时,Realm的写事务未正确完成回滚,导致后续尝试开启新事务时提示「Realm is already in a write transaction」。虽然writeBlocking理论上会在lambda抛出异常时自动回滚事务,但实际场景中可能因异常传播或实例管理问题导致事务残留。

解决方案

方案一:提前检查主键存在性(推荐)

在事务执行写入操作前,先查询是否存在该主键的学生,避免在事务内部抛出异常,确保事务能正常回滚:

修改addStudent函数:

fun addStudent(mID: String, mName: String, mSex: Char) {
    realm.writeBlocking {
        // 先查询是否存在该ID的学生
        val existingStudent = query(Student::class, "_id == $0", mID).first().find()
        if (existingStudent != null) {
            throw IllegalArgumentException("Student ID $mID is already in use")
        }
        // 不存在则写入数据
        copyToRealm(Student().apply {
            _id = mID
            name = mName
            sex = mSex
        })
    }
}

方案二:手动取消异常事务

如果需要保留主键冲突时的原生异常,可在事务内部捕获异常并手动取消事务,确保事务状态正确:

修改addStudent函数:

fun addStudent(mID: String, mName: String, mSex: Char) {
    realm.writeBlocking {
        runCatching {
            copyToRealm(Student().apply {
                _id = mID
                name = mName
                sex = mSex
            })
        }.onFailure { exception ->
            // 手动取消事务
            cancelWrite()
            // 重新抛出异常给上层处理
            throw exception
        }
    }
}

注意事项

  • 不要手动调用realm.close()后重新打开实例,Realm实例是线程安全的,频繁关闭/打开会导致状态混乱。
  • 原按钮点击事件中的runCatching逻辑无需修改,异常会被正常捕获并提示用户。

内容的提问来源于stack exchange,提问作者EvanieWares

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 20:24:32