【问题标题】:RealmChangeListener does not get called when Realm gets updated in NotificationListenerService在 NotificationListenerService 中更新 Realm 时不会调用 RealmChangeListener
【发布时间】:2016-08-08 15:29:01
【问题描述】:

我正在扩展 NotificationListenerService 上进行领域插入,如下所示:

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

使用比 v0.88.3 更新的 Realm,如果在 NLService 中插入任何内容,则不会调用单个 RealmChangeListener (rcl)。

我尝试将 rcl 直接附加到 RealmRealmResultsRealmObject,但没有任何效果。

该应用程序具有例如简单的 rcl 用于 RealmResults<myRealmObject>.size() 和 几个 RecyclerAdapter 和 RealmRecyclerViewAdapter 中的 rcl 永远不会被调用。

但是,重新运行查询会起作用,并且会显示“丢失的数据”。 此外,如果在 ui- 或任何其他线程上插入任何内容,则会调用 rcl 并显示“丢失数据”。

我在 Realm 0.88.3 上呆了几个月,因为我无法将它用于任何较新的 Realm 版本。在 NLService 中调用了 0.88.3 mRealm.refresh();,这在较新的版本中不可用,.waitForChange 无休止地阻塞。

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>

【问题讨论】:

  • 您在哪里尝试添加RealmChangeListener?您是否偶然知道NotificationListenerService 是在后台线程(非looper)、后台线程(带looper)还是在UI 线程上运行?
  • 最大的问题是,NotificationListenerService 是如何在您的 AndroidManifest.xml 中声明的?
  • (注:后面引用github.com/realm/realm-java/issues/3272
  • 我对 NotificationListenerService 不太熟悉,但如果它是在单独的进程中调用的,那就是它不起作用的原因。
  • @EpicPandaForce 查看编辑。所有 RealmChangeListener 都在 UI 线程上。

标签: android realm


【解决方案1】:

我可以看到两种解决方案,要么使用带有 setAutoRefresh(true) 的循环线程 (HandlerThread)(并在 Looper.quit() 之前调用 setAutoRefresh(false)),要么强制刷新线程上的 Realm 实例。


注意:这依赖于包内部的方法。小心。

在 v 1.1.1(和 v1.2.0)中, - 以及 3.0.0 之前的任何版本 - 而不是以下行

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

您可以使用包内部的东西通过与 Realm 实例关联的 HandlerController 在本地线程上强制更新

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

然后调用

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

请注意更改日志的重大更改,因为 0.89.0 更改了迭代行为,并且结果在活动事务期间不再有效;但从 3.0.0 开始,它们又来了。


但是,我还必须注意,如果您的 NotificationListenerService 在远程进程中运行,那么 Realm 实例将无法相互通知。



编辑:

在 Realm Java 3.0.0 中,通知行为被彻底改变,HandlerController 不再存在。

相反,以下应该可以工作:

package io.realm;

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

编辑:

在 Realm 3.2.+ 中,这一切都可用

realm.refresh();

【讨论】:

  • 可以确认,此解决方案有效。但是,ui线程上似乎有一点滞后,我会尝试调查它是否与此有关。感谢您的帮助@EpicPandaForce!
  • 很高兴听到! :) 虽然这更像是一个创可贴而不是修复,所以在此期间正在进行进一步的讨论以弄清楚发生了什么。
  • 而且显然HandlerController 仍然是它原来的位置,这部分像以前一样工作,所以这仍然在 2.0.2 下工作。
  • 我确认即使使用 Realm 2.2.1 也可以使用它,它可以挽救生命.. 我必须在 AsyncTask.doInBackground() 的开头调用它才能获得实际数据(如果我调用它最后,我看到更改后第一次下一次调用的旧数据)。我想知道领域中非 Looper 线程中未更新数据的大问题怎么可能必须由 SO 中的某个人解决,而不是由领域开发人员默认 api.. 这确实是个大问题,这很有帮助。
  • @luky 从技术上讲,我在 3 个月前提交了一个问题 here 但它是 P2: Design Required 所以就是这样。当结果集成完成后我将不得不更新这篇文章(那时这个解决方案将不再有效),但那可能是明年。
猜你喜欢
  • 2015-11-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-03
  • 2015-04-11
  • 1970-01-01
相关资源
最近更新 更多