RealmChangeListener does not get called when Realm gets updated in NotificationListenerService

不羁岁月 提交于 2019-11-26 04:27:28

问题


I\'m doing Realm insertions on a extended NotificationListenerService, like this:

public class NLService extends NotificationListenerService {

    @Override
    public void onNotificationPosted(StatusBarNotification sbn) {

        // building realmObject here

        mRealm = Realm.getDefaultInstance();
        RealmHelper.saveObj(myRealmObject, mRealm);
    //  mRealm.waitForChange(); / mRealm.refresh();
        mRealm.close();
    }
}


public class RealmHelper {

    public static RealmModel saveObj(RealmObject realmObject, Realm realm) {
        realm.beginTransaction();
        RealmObject newRealmObject = realm.copyToRealm(realmObject);
        realm.commitTransaction();
        return newRealmObject;
    }
}

Using Realm newer than v0.88.3, not a single RealmChangeListener (rcl) gets called if anything gets inserted in NLService.

I tried attaching rcl\'s directly to Realm, RealmResults and RealmObject, nothing works.

The App has for example simple rcl\'s for RealmResults<myRealmObject>.size() and several RecyclerAdapters and the rcl inside RealmRecyclerViewAdapter is never called.

Rerunning queries however works and the \"missing data\" shows up. Also if anything gets inserted on ui- or any other thread, rcl\'s get called and \"missing data\" shows up.

I stayed for months on Realm 0.88.3 because I can not bring it to work with any newer Realm version. With 0.88.3 mRealm.refresh(); was called in NLService, this is not available in newer versions and .waitForChange blocks endlessly.

Manifest.xml:

<service
    android:name=\".service.NLService\"
    android:label=\"@string/nl_service\"
    android:permission=\"android.permission.BIND_NOTIFICATION_LISTENER_SERVICE\">
    <intent-filter>
        <action android:name=\"android.service.notification.NotificationListenerService\"/>
    </intent-filter>
</service>

回答1:


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


来源:https://stackoverflow.com/questions/38833163/realmchangelistener-does-not-get-called-when-realm-gets-updated-in-notificationl

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!