从多个线程访问RealmDB

3

我想了解在多个线程中使用RealmDB的推荐实践。

我的情况是:我正在使用一个线程循环遍历RealmDB中的记录,并执行某些操作。根据上一个操作的响应,我想从另一个线程中删除记录。

如何最好地实现这一点?

1个回答

2
你可以在不同的线程之间传递RealmObject字段值 (例如id, primaryKey),这意味着当你在其他线程上完成"action1"时,你可以将id传递到负责处理Realm操作的线程,查询需要被删除的Object并从Realm中删除它们,你可以使用executeTransactionAsync进一步使删除操作与Realm操作线程隔离。
编辑
  • 在Realm中,写操作不会阻塞读操作。
  • RealmResults和RealmObjects是活动对象,直到我们关闭了Realm实例。
  • 如果您将读操作作为Observable使用,则所有后续修改都将被通知。如果不想使用Observable,则也可以使用addChangeListener。
让我们看一些代码:
假设在你的某个类中有一个Realm实例,并且你在ThreadA(本例中是mainThread) 上进行读取操作。
realm.where(GitHubUser.class).findAll().asObservable()
        .filter(RealmResults::isLoaded)
        .filter(RealmResults::isValid)
        .subscribeOn(AndroidSchedulers.mainThread())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(gitHubUsers -> {
            for (GitHubUser gitHubUser : gitHubUsers) {
                Log.e("TAG", "data = " + gitHubUser.getLogin());
            }
        });

还有一个对应的 addChangeListener 版本

RealmResults realmResults = realm.where(GitHubUser.class).findAll();
realmResults.addChangeListener(new RealmChangeListener<RealmResults>() {
    @Override
    public void onChange(RealmResults element) {
        for (GitHubUser gitHubUser : gitHubUsers) {
            Log.e("TAG", "data = " + gitHubUser.getLogin());
        }
    }
});

for (GitHubUser gitHubUser : gitHubUsers) {
    Log.e("TAG", "data = " + gitHubUser.getLogin());
}

假设你已经获得了触发器并希望在单独的线程上删除其中一个条目,那么你应该做的是获取一个新的Realm实例,按下面所示删除条目,然后关闭Realm实例。这样,您将不会遇到任何线程问题,并且在您删除条目后,您的读取查询会收到通知,您可以使用更新后的数据更新视图。

new Thread(() -> {
    Realm realm1 = Realm.getDefaultInstance();

    GitHubUser gitHubUser = realm1.where(GitHubUser.class)
            .equalTo("login", "loginString")
            .findFirst();

    if (gitHubUser != null) {
        realm1.executeTransaction(realm2 -> gitHubUser.deleteFromRealm());
    }
    realm1.close();
}).run();

Viraj,我无法使用executeTransactionAsync,因为我需要仅在接收到外部事件时才在单独的线程上执行删除操作。你提到的另一种解决方案,我已经知道了,我的问题是:假设您在数据库中有10条记录。您正在Thread A中循环遍历它们。您从ThreadA发布Record1,并同时在ThreadB上接收Record1的响应。现在,在这种情况下,您仍然在Thread A中循环遍历Record 2到10,但您需要从Thread B中删除Record1。我们如何安全地执行此操作? - ATO
@ATO 请查看更新后的回答,如果不符合您的要求,请告诉我。 - Viraj Tank
谢谢,这对我来说似乎是一个不错的解决方案。让我试一下。 - ATO

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接