koperko
koperko

Reputation: 2487

Wait for data update in realm-java between threads

I am having trouble with waiting for fresh data on a worker thread. The data object is copied to realm on a main thread, but almost immediately after that I need to access this object from a worker thread, which then reports that no such object exists in realm right now ( its newly opened realm instance ) . I remember that there was a method load() that would block execution to the point of next update, but it was removed in newer versions. And I can't use change notification for this as this is not a Looper thread..

The only way I can think of right now is to sleep the thread for some magic period of time and pray to god that it has updated already, but that approach is imho wildly indeterministic.

Can anybody advise here, how can I ensure that I read the most current data at the time ?

Upvotes: 0

Views: 1700

Answers (3)

Sifundo Moyo
Sifundo Moyo

Reputation: 185

using realm.beginTransaction() and realm.commitTransaction() instead of realm.executeTransaction(Realm.Transaction)

The problem with this is that executeTransaction() automatically handles calling realm.cancelTransaction() in case an exception is thrown, while the other alternative typically neglects the try-catch.

Yes, you’re supposed to call cancel on transactions that aren’t going to end up being committed.

For example, on background threads:

    // SAY NO TO THIS
Realm realm = Realm.getDefaultInstance();
realm.beginTransaction(); // NO
realm.copyToRealm(dog)
realm.commitTransaction(); // NO NO NO NO NO
    // YOU NEED TO CLOSE THE REALM

// ----------------------

// SAY YES TO THIS
Realm realm = null;
try { // I could use try-with-resources here
    realm = Realm.getDefaultInstance();
    realm.executeTransaction(new Realm.Transaction() {
        @Override
        public void execute(Realm realm) {
            realm.insertOrUpdate(dog);
        }
    });
} finally {
  if(realm != null) {
    realm.close();
  }
}

// OR IN SHORT (Retrolambda)

try(Realm realmInstance = Realm.getDefaultInstance()) {
    realmInstance.executeTransaction((realm) -> realm.insertOrUpdate(dog));
}

The problem with this is that on background threads, having an open Realm instance that you don’t close even when the thread execution is over is very costly, and can cause strange errors. As such, it’s recommended to close the Realm on your background thread when the execution is done in a finally block. This includes IntentServices.

Upvotes: 0

EpicPandaForce
EpicPandaForce

Reputation: 81539

A possible hack would be to create a transaction that you cancel at the end.

realm.beginTransaction(); // blocks while there are other transactions
... // you always see the latest version of the Realm here
realm.cancelTransaction();

This works if the thread is started after the UI thread saves the object into the Realm.

You can also try this workaround: https://stackoverflow.com/a/38839808/2413303 (although it doesn't really help with waiting)

Upvotes: 1

Alex Shutov
Alex Shutov

Reputation: 3282

try using QueryListener, which is trigger whenewer object, satisfying certain criteria is updated

Upvotes: 0

Related Questions