Android使用Realm-java时如何仅监听追踪INSERT插入操作?
问题解答
Realm-java 没有提供专门仅响应INSERT操作的开箱即用官方监听器,但只需要极少量额外代码就能实现你的需求,完全适配服务端数据乱序推送的场景,具体有两种可行实现方案:
方案1:基于表级查询监听器+原生变更集过滤插入事件
Realm 自带的RealmChangeListener默认会同时响应插入、更新、删除三类变更,不需要自己全量对比集合差异,直接用回调返回的变更集就能精准捕获插入操作:
- 不要注册全局Realm实例的变更监听器,针对需要监听的表单独注册异步查询结果监听器,比如针对
Person表的监听示例:
RealmResults<Person> persons = realm.where(Person.class).findAllAsync(); persons.addChangeListener((newPersons, changeSet) -> { // changeSet 原生返回所有插入项的索引,不会和更新、删除事件混淆 int[] insertedIndexes = changeSet.getInsertions(); for (int index : insertedIndexes) { Person insertedPerson = newPersons.get(index); // 执行新插入Person的关联逻辑 realm.executeTransaction(r -> { RealmResults<Pet> relatedPets = r.where(Pet.class) .equalTo("ownerId", insertedPerson.getId()) .findAll(); insertedPerson.setPets(relatedPets); }); } });
- 给
Pet表也注册结构完全一致的监听器,在Pet插入时反向查库中是否已经存在对应id的Person,存在就直接建立关联即可。
注意:该方案的插入项判断是Realm底层自动计算的,性能开销极低,只要你没有手动修改旧数据的逻辑,就不会出现误判。
方案2:封装统一存库入口,自定义插入事件
如果不想依赖Realm的原生变更监听逻辑,可以直接封装一层统一的服务端数据存库方法,逻辑更可控,完全没有误判可能:
- 所有服务端通过websocket推送的
Person、Pet数据,都统一走自定义的saveIfAbsent()方法存库,方法内先通过主键判断数据是否已存在:- 数据已存在:直接跳过,不做额外处理
- 数据不存在:执行插入逻辑,插入完成后直接抛出对应类型的插入事件(可以用LiveData、本地广播或者项目中已在用的轻量事件组件实现)
- 在插入事件的订阅处实现关联逻辑:收到
Person插入事件就查对应ownerId的Pet,收到Pet插入事件就查对应id的Person,查到匹配数据就直接建立关联。
这个方案和Realm原生能力完全解耦,逻辑直白,非常适合你这种数据全由服务端推送、客户端写入入口完全可控的场景。
场景适配提示
两种方案都能完美覆盖服务端数据乱序下发的场景,不管Person和Pet的到达顺序差多久,只要后到的数据插入完成,就会自动触发关联检查,不需要额外写时序控制逻辑,也不需要做临时数据缓存。
注意不要在回调里做和Realm操作无关的耗时任务,Realm带索引的主键查询速度极快,关联操作的性能开销可以忽略,不会影响主线程流畅度。
内容的提问来源于stack exchange,提问作者Est Stalegaykin
相关产品推荐
相关产品推荐

