Android中使用Realm 5.0.0同时执行插入与删除对象问题
嘿,我来帮你搞定这个Realm 5.0.0的问题!你遇到的这种「只能完成其中一个操作」的情况,根源大概率是没遵守Realm的线程隔离规则,或者两个线程的事务没做同步导致的。下面我给你分析原因并提供可行的解决方案:
问题根源解析
Realm有两个核心规则你可能没注意到:
- 线程隔离:每个线程必须拥有独立的Realm实例,不能跨线程共享Realm对象、
RealmResults或RealmObject - 事务原子性:如果把删除和拆分成两个独立线程的事务,很可能出现线程执行顺序混乱、事务互相覆盖的情况,最终只有最后完成的那个操作生效
解决方案1:同一个事务内完成删除+插入(推荐)
把删除和插入放在同一个Realm事务里,既能保证操作的原子性(要么都成功,要么都失败),又能避免线程同步问题。代码示例如下:
public static void processSKUList(final ArrayList<SKUItem> skuItems) { new Thread(new Runnable() { @Override public void run() { // 获取当前线程专属的Realm实例 Realm realm = Realm.getDefaultInstance(); try { realm.executeTransaction(new Realm.Transaction() { @Override public void execute(Realm realm) { // 1. 先执行删除操作(这里假设你通过SKU的id来匹配删除,需根据你的实体类调整条件) String[] skuIds = extractSKUIds(skuItems); realm.where(SKUItem.class) .in("id", skuIds) .deleteAllFromRealm(); // 2. 再执行插入操作 realm.copyToRealmOrUpdate(skuItems); } }); } finally { // 必须在finally块关闭Realm实例,避免内存泄漏 if (!realm.isClosed()) { realm.close(); } } } }).start(); } // 辅助方法:提取SKU列表中的id数组,用于删除条件匹配 private static String[] extractSKUIds(ArrayList<SKUItem> skuItems) { String[] ids = new String[skuItems.size()]; for (int i = 0; i < skuItems.size(); i++) { ids[i] = skuItems.get(i).getId(); } return ids; }
解决方案2:强制线程顺序执行(不推荐,仅当必须拆分线程时用)
如果因为业务需求必须拆分两个线程,那要确保第一个线程的事务完全完成后,再启动第二个线程。可以用Thread.join()实现同步:
public static void removeSKUList(final ArrayList<SKUItem> skuItems) { // 定义删除线程 final Thread deleteThread = new Thread(new Runnable() { @Override public void run() { Realm realm = Realm.getDefaultInstance(); try { realm.executeTransaction(new Realm.Transaction() { @Override public void execute(Realm realm) { String[] skuIds = extractSKUIds(skuItems); realm.where(SKUItem.class) .in("id", skuIds) .deleteAllFromRealm(); } }); } finally { realm.close(); } } }); // 定义插入线程,等待删除线程完成后再执行 final Thread insertThread = new Thread(new Runnable() { @Override public void run() { try { // 强制等待删除线程执行完毕 deleteThread.join(); } catch (InterruptedException e) { e.printStackTrace(); } Realm realm = Realm.getDefaultInstance(); try { realm.executeTransaction(new Realm.Transaction() { @Override public void execute(Realm realm) { realm.copyToRealmOrUpdate(skuItems); } }); } finally { realm.close(); } } }); // 启动线程 deleteThread.start(); insertThread.start(); }
额外推荐:用Realm自带的异步事务
如果你是在Android环境下开发,推荐用Realm提供的executeTransactionAsync,它会自动管理后台线程,且回调在UI线程执行,不用自己手动处理线程:
public static void processSKUListAsync(final ArrayList<SKUItem> skuItems) { Realm.getDefaultInstance().executeTransactionAsync( // 后台执行的事务逻辑 new Realm.Transaction() { @Override public void execute(Realm realm) { String[] skuIds = extractSKUIds(skuItems); realm.where(SKUItem.class) .in("id", skuIds) .deleteAllFromRealm(); realm.copyToRealmOrUpdate(skuItems); } }, // 操作成功的回调(UI线程) new Realm.Transaction.OnSuccess() { @Override public void onSuccess() { // 这里可以更新UI提示操作完成 } }, // 操作失败的回调(UI线程) new Realm.Transaction.OnError() { @Override public void onError(Throwable error) { error.printStackTrace(); } } ); }
内容的提问来源于stack exchange,提问作者Rajesh Gauswami
相关产品推荐
相关产品推荐

