如何编写接收ArrayList的RealmList Setter并更新其中对象?
关于RealmList接收ArrayList参数的Setter实现与对象更新方案
一、接收ArrayList参数的RealmList最佳Setter方法
首先得明确RealmList的核心特性:它是Realm的托管集合,和普通ArrayList不一样——如果你的RealmObject已经被Realm管理(比如从数据库查询出来的实例),直接给RealmList赋值新的引用会让它脱离Realm的追踪,后续操作都会出问题。所以最佳Setter的核心是修改现有RealmList的内容,而非替换引用。
推荐的通用写法如下,兼顾托管和非托管两种场景:
public void setMyRealmList(ArrayList<ObjectExtendsRealmObject> arrayList) { // 先清空原有内容,避免残留旧数据 this.myRealmList.clear(); if (arrayList == null || arrayList.isEmpty()) { return; } // 判断当前对象是否处于Realm托管状态 if (this.isManaged()) { // 托管状态下,必须将ArrayList中的对象转为Realm托管对象才能添加 Realm realm = this.getRealm(); // copyToRealmOrUpdate:有主键则更新已有对象,无主键则插入新对象 this.myRealmList.addAll(realm.copyToRealmOrUpdate(arrayList)); } else { // 非托管状态(比如刚new出来的RealmObject),直接添加即可 this.myRealmList.addAll(arrayList); } }
为什么这么写?
- 避免直接替换RealmList引用,保证集合始终处于Realm的管理下;
- 区分托管/非托管场景,防止添加未托管对象导致的异常;
- 用
copyToRealmOrUpdate处理对象的插入/更新,适配不同主键场景。
二、用ArrayList更新RealmList中的现有对象
如果你的需求不是直接替换整个列表,而是根据唯一标识(比如主键)更新匹配的对象、新增不存在的对象、删除不再需要的对象,那得在事务里做完整的同步操作(托管状态下必须用事务)。
假设你的ObjectExtendsRealmObject有主键id(用@PrimaryKey标注),推荐写法:
public void updateMyRealmList(ArrayList<ObjectExtendsRealmObject> newList) { // 非托管状态直接替换即可,还没进入Realm管理,操作更自由 if (!this.isManaged()) { this.myRealmList.clear(); this.myRealmList.addAll(newList); return; } // 托管状态必须在事务中修改 Realm realm = this.getRealm(); realm.executeTransaction(r -> { // 1. 收集现有列表中所有对象的主键 Set<Long> existingIds = new HashSet<>(); for (ObjectExtendsRealmObject item : this.myRealmList) { existingIds.add(item.getId()); } // 2. 遍历新列表:更新已有对象,新增不存在的对象 Set<Long> newIds = new HashSet<>(); for (ObjectExtendsRealmObject newItem : newList) { newIds.add(newItem.getId()); // 查找现有列表中是否有匹配主键的对象 ObjectExtendsRealmObject existingItem = this.myRealmList.where() .equalTo("id", newItem.getId()) .findFirst(); if (existingItem != null) { // 存在则手动更新字段(这里根据你的对象字段调整) existingItem.setName(newItem.getName()); existingItem.setValue(newItem.getValue()); // ... 其他需要同步的字段 } else { // 不存在则添加新的托管对象 this.myRealmList.add(r.copyToRealmOrUpdate(newItem)); } } // 3. 删除不在新列表中的旧对象(必须用迭代器删除托管集合元素) Iterator<ObjectExtendsRealmObject> iterator = this.myRealmList.iterator(); while (iterator.hasNext()) { ObjectExtendsRealmObject item = iterator.next(); if (!newIds.contains(item.getId())) { iterator.remove(); } } }); }
额外注意事项
- 如果你的RealmObject没有主键,更新匹配会非常麻烦(没有唯一标识),建议尽量给RealmObject添加主键;
- 事务操作尽量放在后台线程,避免主线程耗时导致ANR;
- 操作完成后记得正确关闭Realm实例(如果是手动获取的话)。
内容的提问来源于stack exchange,提问作者bycfly
相关产品推荐
相关产品推荐

