我试图使用GreenRobot在片段之间共享RealmResults。当用户点击某些按钮更改我想要显示的数据时,我调用invalidateRealmResult:
public void invalidateRealmResult() {
RealmQuery<Climb> realmQuery = mRealm.where(Climb.class);
// other query modifiers added here....
mResult = realmQuery.findAllSorted("date", Sort.ASCENDING);
RealmChangeListener listener = new RealmChangeListener<RealmResults<Climb>>() {
@Override
public void onChange(RealmResults<Climb> element) {
Log.d(TAG, "Realmresult onchange");
EventBus.getDefault().postSticky(new RealmResultsEvent(mResult));
}
};
mResult.addChangeListener(listener);
EventBus.getDefault().postSticky(new RealmResultsEvent(mResult));
}
我的greenrobot活动如下:
public class RealmResultsEvent {
public RealmResult mResult;
public RealmResultsEvent(RealmResult result){
this.mResult = result
}
}
任何需要使用新结果更新的片段都会订阅该事件:
@Subscribe(sticky = true)
public void onRealmResultEvent(RealmResultsEvent event) {
mResult = event.mResult;
updateView();
}
@Override
public void onStop() {
super.onStop();
EventBus.getDefault().unregister(this);
}
@Override
public void onStart() {
super.onStart();
EventBus.getDefault().register(this);
}
我确保所有片段都在onStart()中订阅并在onStop()中取消订阅。
我的问题是,新的活动帖子似乎不会覆盖旧的RealmResults
。我可以告诉RealmResults
没有被销毁,因为每当我添加到领域数据库时,RealmChangeListener
中的日志消息都会被调用越来越多,并且每隔一段时间UI就会显示错误的查询结果。
05-13 10:36:55.523 17684-17684/com.example.grant.wearableclimbtracker D/MainActivity: Realmresult onchange
05-13 10:36:55.536 17684-17684/com.example.grant.wearableclimbtracker D/MainActivity: Realmresult onchange
05-13 10:36:55.544 17684-17684/com.example.grant.wearableclimbtracker D/MainActivity: Realmresult onchange
05-13 10:36:55.551 17684-17684/com.example.grant.wearableclimbtracker D/MainActivity: Realmresult onchange
05-13 10:36:55.558 17684-17684/com.example.grant.wearableclimbtracker D/MainActivity: Realmresult onchange
05-13 10:36:55.566 17684-17684/com.example.grant.wearableclimbtracker D/MainActivity: Realmresult onchange
05-13 10:36:55.574 17684-17684/com.example.grant.wearableclimbtracker D/MainActivity: Realmresult onchange
05-13 10:36:55.583 17684-17684/com.example.grant.wearableclimbtracker D/MainActivity: Realmresult onchange
05-13 10:36:55.591 17684-17684/com.example.grant.wearableclimbtracker D/MainActivity: Realmresult onchange
05-13 10:36:55.600 17684-17684/com.example.grant.wearableclimbtracker D/MainActivity: Realmresult onchange
05-13 10:36:55.608 17684-17684/com.example.grant.wearableclimbtracker D/MainActivity: Realmresult onchange
05-13 10:36:55.616 17684-17684/com.example.grant.wearableclimbtracker D/MainActivity: Realmresult onchange
每当我做出改变时,它都会以一个交替的3,6,12,6,3 ...次来调用听众,重复这种模式。不确定这意味着什么,或者该信息是否有助于任何人。
答案 0 :(得分:1)
根据问题中提供的示例代码段,很难说每次调用mResult
之前为什么之前的invalidateRealmResult()
没有获得GC。我同意你的评估,它似乎不是GC,因为听众仍在回应。我的猜测是,我们在这里缺少对mResult的额外参考。
一般领域使用:
观察样品的一个观察结果。目前尚不清楚,为什么每次将Climb结果添加到数据库时都需要重新运行查询。领域results are live,意味着如果与查询结果匹配的基础数据发生更改,则数据会自动更新。无需重新查询。添加更改侦听器,为您提供了一种订阅该事件(结果数据已更改)的方法,并在您的UI中做出反应。您可以通过将代码调整为以下内容来简化操作并避免此GC问题:
@Override
public void onStop() {
super.onStop();
}
@Override
public void onStart() {
super.onStart();
mResult = fetchRealmResults()
}
public void fetchRealmResults() {
RealmQuery<Climb> realmQuery = mRealm.where(Climb.class);
// other query modifiers added here....
// Async suffix is optional here, but will push
// the work to a worker thread and then come back
// with the results on the main thread.
mResult = realmQuery.findAllSortedAsync("date", Sort.ASCENDING);
RealmChangeListener listener = new
RealmChangeListener<RealmResults<Climb>>() {
@Override
public void onChange(RealmResults<Climb> element) {
// This will fire anytime there is a change
// to the underlying database that affects
// the results of this query.
Log.d(TAG, "Realmresult onchange");
updateView();
}
};
mResult.addChangeListener(listener);
}
注意我为了简单起见拿出了GreenRobot的东西,但你可以继续使用它。我只会使用它来触发事件到您的片段,但不会发送更新的结果,因为您的片段已经在其现有的mResult
引用中获得了更新的结果。有意义吗?
答案 1 :(得分:0)
我设法删除了大量代码,直到我缩小了问题范围。它与eventbus无关。出于某种原因,当我将realmresult重新分配给新的查询结果时,它不会垃圾收集旧的realmresult并且旧结果的changelisteners仍在触发。这创造了一个竞争条件,最后完成的任何一个听众都会出现在我的UI上。
我通过在重新分配字段之前移除侦听器来伪修复此问题:
public void invalidateRealmResult() {
RealmQuery<Climb> realmQuery = mRealm.where(Climb.class);
// other query modifiers added here....
// ADDED THIS TO AVOID CALLING MULTIPLE LISTENERS
if(mResult != null) {
mResult.removeAllChangeListeners();
}
mResult = realmQuery.findAllSorted("date", Sort.ASCENDING);
RealmChangeListener listener = new RealmChangeListener<RealmResults<Climb>>() {
@Override
public void onChange(RealmResults<Climb> element) {
Log.d(TAG, "Realmresult onchange");
EventBus.getDefault().postSticky(new RealmResultsEvent(mResult));
}
};
mResult.addChangeListener(listener);
EventBus.getDefault().postSticky(new RealmResultsEvent(mResult));
}
我称之为伪修复,因为它没有表现出奇怪的行为,但我很确定仍然存在不是GC的RealmResult对象,我不知道为什么。