Android Realm报错:无法在写入事务外修改托管对象
嘿,我来帮你搞定这个Realm更新的问题!
问题根源分析
你遇到的Cannot modify managed objects outside of a write transaction错误,主要有两个核心原因:
- 从
GetRecordById返回的是Realm的托管对象(managed object),这类对象的生命周期和Realm实例绑定,且只能在Realm写事务内部修改。如果你在事务外修改它的属性,就会触发报错。 - 你的
UpdateRecordinRealmByID方法里有个致命逻辑错误:recordByid = passedObject;这行只是把局部变量的引用指向了新对象,并没有把passedObject的属性值同步到从Realm查询出来的托管对象上,后续的insertOrUpdate操作自然也达不到预期效果。
修正方案
1. 先修复Realm实例泄漏问题
你的GetRecordById方法创建了Realm实例但没有关闭,会导致资源泄漏,先把它修正:
public static <T extends RealmObject> T GetRecordById(Class<T> clazz, Integer id) { Realm realm = getRealmInstance(); try { RealmQuery<T> queryForUsern = realm.where(clazz).equalTo("RealmId", id); T recordByid = queryForUsern.findFirst(); // 可选:如果需要在事务外修改对象,返回非托管副本 // return recordByid != null ? realm.copyFromRealm(recordByid) : null; return recordByid; } finally { realm.close(); // 必须关闭Realm实例 } }
2. 简化并修正更新方法
首先确保你的Realm实体类已经正确设置主键(这是copyToRealmOrUpdate正常工作的前提):
public class YourModel extends RealmObject { @PrimaryKey // 必须添加主键注解 private int RealmId; // 其他15个字段... }
然后把更新方法简化成和插入逻辑一致的写法——Realm的copyToRealmOrUpdate本身就支持“存在则更新,不存在则插入”的逻辑,完全不需要先查询再赋值:
public static <T extends RealmObject> void UpdateRecordinRealm(final T passedObject) { Realm realm = getRealmInstance(); realm.executeTransaction(new Realm.Transaction() { @Override public void execute(Realm realm) { realm.copyToRealmOrUpdate(passedObject); } }); realm.close(); }
3. 安全修改对象的正确流程
如果你需要在Fragment之间传递并修改对象,推荐使用非托管对象(脱离Realm实例绑定的副本),这样可以在事务外自由修改属性:
// 在第二个Fragment获取对象时,获取非托管副本 YourModel model = RealmHelper.GetRecordById(YourModel.class, 1); if(model != null) { YourModel unmanagedModel = realm.copyFromRealm(model); // 自由修改非托管对象的属性 unmanagedModel.setField5("第二个Fragment的输入值"); unmanagedModel.setField6("..."); // 调用更新方法同步到Realm RealmHelper.UpdateRecordinRealm(unmanagedModel); }
关键注意点
- 托管对象只能在写事务内部修改,非托管对象可以在任意地方修改,之后通过
copyToRealmOrUpdate同步到Realm。 - 所有Realm实例必须在使用后关闭,用
try-finally包裹是最安全的方式。 - 利用
copyToRealmOrUpdate可以大幅简化你的插入/更新逻辑,不需要区分插入和更新操作。
内容的提问来源于stack exchange,提问作者Tushar Pingale
相关产品推荐
相关产品推荐

