ATO
ATO

Reputation: 574

Accessing RealmDB from multiple Threads

I would like to know if there is any recommended practice of using RealmDB across multiple threads.

My scenario: I am looping through the records in RealmDB using one thread and doing some action. Based on the response from the previous action I would like to remove the records from another thread.

What would be best way to achieve this?

Upvotes: 3

Views: 593

Answers (1)

Viraj Tank
Viraj Tank

Reputation: 1285

You can pass RealmObject field values (e.g. id, primaryKey) across the threads, which means that when you are done with your "action1" on the other thread, you can transfer the id(s) to the thread that is responsible for handling Realm operations, query the Object(s) which needs to be removed and delete them from Realm, you can executeTransactionAsync to further takeaway delete operation(s) from the thread where Realm is operating.

EDIT

  • In Realm Write operations don't block Read operations.
  • RealmResults & RealmObjects are LIVE objects until we close Realm instance
  • If you use Read operations as Observable, all further modification will be notified, If you don't want to use Observable you can also use addChange listener.

Lets have a look at some code:

Lets say in one of your class you have a Realm instance, and you are doing read operation on ThreadA (mainThread in this example)

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());
            }
        });

And a corresponding addChangeListener version

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());
}

and let's say you get the trigger and want to delete one of the entry on a separate thread, what you should do is, get a new Realm instance, delete the entry as shown below and close the Realm instance. This way you will not face any thread issue and your Read query gets a notification after you delete the entry and you can update your view with updated data.

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();

Upvotes: 2

Related Questions