【问题标题】:Accessing RealmDB from multiple Threads从多个线程访问 RealmDB
【发布时间】:2016-11-07 12:43:01
【问题描述】:

我想知道是否有任何推荐的跨多个线程使用 RealmDB 的做法。

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

实现这一目标的最佳方法是什么?

【问题讨论】:

    标签: android multithreading realm


    【解决方案1】:

    您可以跨线程传递 RealmObject 字段值(例如 id、primaryKey),这意味着当您在另一个线程上完成“action1”时,您可以将 id 传递给负责的线程对于处理 Realm 操作,查询需要删除的 Object(s) 并将其从 Realm 中删除,您可以执行 TransactionAsync 以进一步从 Realm 正在运行的线程中取出删除操作。

    编辑

    • 在 Realm 中写入操作不会阻塞读取操作。
    • RealmResults 和 RealmObjects 在我们关闭 Realm 实例之前都是 LIVE 对象
    • 如果您将 Read 操作用作 Observable,所有进一步的修改都会收到通知,如果您不想使用 Observable,您也可以使用 addChange 监听器。

    让我们看一些代码:

    假设在您的一个类中,您有一个 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,因为我需要在单独的线程上执行删除,只有当它接收到外部事件时。你提到的另一个解决方案我知道我的问题是让我们说:你在 DB 中有 10 条记录。您正在线程 A 中循环它们。您从 ThreadA 发布 Record1,同时您在 ThreadB 上收到 Record1 的响应。现在在这种情况下,您仍然在线程 A 中循环记录 2 到 10,但您需要从线程 B 中删除 Record1。我们如何安全地执行此操作?
    • @ATO 请找到更新后的答案,如果不是您要找的,请告诉我。
    • 谢谢,这在我看来是一个很好的解决方案。让我试试看。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-08-28
    • 2015-12-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多