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
相关产品推荐
相关产品推荐

