Realmchangelistener Does Not Get Called When Realm Gets Updated in Notificationlistenerservice

RealmChangeListener does not get called when Realm gets updated in NotificationListenerService

I can see two solutions to this, either use a looper thread (HandlerThread) with setAutoRefresh(true) (and call setAutoRefresh(false) before Looper.quit()), or force a refresh for the Realm instance on the thread.


NOTE: This relies on package-internal methods. Beware.

In v 1.1.1 (and v1.2.0), - and any version before 3.0.0 - instead of the following line

//  mRealm.waitForChange(); / mRealm.refresh();

You could force the update on the local thread through the HandlerController associated with the Realm instance using package-internal stuff

package io.realm;

public class RealmRefresh {
public static void refreshRealm(Realm realm) {
Message message = Message.obtain();
message.what = HandlerControllerConstants.LOCAL_COMMIT;
realm.handlerController.handleMessage(message);
}
}

And then call

    mRealm = Realm.getDefaultInstance();
RealmHelper.saveObj(myRealmObject, mRealm);
RealmRefresh.refreshRealm(mRealm);
mRealm.close();

Please note the change log's breaking changes though, because 0.89.0 changed iteration behavior, and results are no longer live during an active transaction; but from 3.0.0 they are again.


However, I must also note that if your NotificationListenerService is running in a remote process, then the Realm instances won't be able to notify each other.



EDIT:

In Realm Java 3.0.0, the notification behavior was changed completely, and HandlerController no longer exists.

Instead, the following should work:

package io.realm;

public class RealmRefresh {
public static void refreshRealm(Realm realm) {
realm.sharedRealm.refresh();
}
}

EDIT:

In Realm 3.2.+, this is all available with

realm.refresh();

Realm returning stale data

That's because

// This function simply stores a Realm model for all the data that has been uploaded to the server
private fun markDataAsUploaded(dataToUpload: List<CallLog>) {
realm = Realm.getDefaultInstance()
for (data in dataToUpload) {
realm.beginTransaction()
val callLogUploaded = realm.createObject(CallLogUploaded::class.java)
callLogUploaded.callDate = data.callDate

realm.commitTransaction()
}
}

This method has quite a few errors that I had written about a long time ago

  • The Realm instance is opened, but never closed

  • There is a new transaction per every element, rather than inserting all elements in a single transaction

If you don't close the Realm instance (each instance requires its own close() call), then your Realm instance will never update unless you actually begin a transaction and do things inside the transaction.

You have three solutions:

1.) do your logic on the background thread inside a transaction, if there is nothing to be done, then cancel the transaction - queries made in transactions are never stale

2.) make sure the Realm instance is closed properly (although this is definitely a necessity on any non-autoupdating thread)

3.) a hacky solution is to call RealmRefresh.refreshRealm() after getDefaultInstance() according to my answer on Stack Overflow which relies on package-private API, but it works to solve this issue


Typically you need to open the Realm instance at the beginning of the thread, and close it at the end of the thread.

so, it's basically one big try(Realm realm = Realm.getDefaultInstance() { ... } for onHandleIntent().


enqueue(new Callback() { @Override public void onSuccess(..) {...} runs on the UI thread. To run it on the current thread, you should use call.execute().


instead of

for (data in dataToUpload) {
realm.beginTransaction()
val callLogUploaded = realm.createObject(CallLogUploaded::class.java)
callLogUploaded.callDate = data.callDate

realm.commitTransaction()
}

do

realm.beginTransaction()
for (data in dataToUpload) {
val callLogUploaded = realm.createObject(CallLogUploaded::class.java)
callLogUploaded.callDate = data.callDate
}
realm.commitTransaction()

In order to understand about version retention you can read https://medium.com/@Zhuinden/understanding-realm-version-retention-and-synchronization-9a513c2445bb .

Realm Inconsistent results

This answer applies if you use Schedulers.io():

Have you considered closing your Realm instance that you open on your thread pool?

Because if you don't close the Realm (which you don't), then you'll experience version retention and your Realm instance in your background thread will never get updated again.

Also consider refreshing the Realm after opening the instance using this force-refresh workaround.

But also make sure you close the instance. In fact, considering you're trying to use a background thread for your query, you should consider using realm.copyFromRealm(realmResults) so that you can close the instance freely.

Realm save data in one thread acquire in another

I found a workaround - even if I don't need any transaction I call .beginTransaction() before call where(clazz.class) and data is up to date.

Wait for data update in realm-java between threads

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)



Related Topics



Leave a reply



Submit