简体   繁体   中英

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 ?

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 )

尝试使用QueryListener,这是在满足特定条件的ewewer对象更新时触发的

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM