问题
Long story short: I do not know why my RealmChangeListener does not trigger as intended under certain circumstances and am looking for advice on why a RealmChangeListener
could not be working.
Update: I have verified that the RealmResults
stay valid = true; loaded=false.
If I execute RealmResults.load()
after adding the change listener, it will output a vague Throwing Exception 7
in the log and a BadVersionException
when I step through the Realm source. I think this exception makes some sense, the asynchronous write updated the Realm
and therefore the query seems to no longer work. However, both the executeTransactionAsync
that writes in the MainActivity
as well as the asynchronous queries are started from the main thread.
-
I have a MainActivity, in which upon pressing a button an asynchronous write will be performed.
I have another button that opens a second activity that displays data.
The second activity uses a ViewPager with a fragment for each tab. Each tab has a different query.
So what happens now is the following: I open the second activity, which instantiates four fragments, not attaching them to the activity.
The activity then executes queries, passing each RealmResults
to the fragment, in which a RealmChangeListener
will be installed to display the data once it is loaded. Could it be that the RealmChangeListener
does not work when the fragment is not attached to an Activity?
Anyway, this is the method in the fragment that receives the RealmResults
(created by findAllAsyncSorted()
) and is supposed to update the data on the Adapter:
public void updateData(OrderedRealmCollection<Bean> realmCollection) {
Timber.v("Delegated data to fragment of adapter %s.", adapter);
this.data = (RealmResults<Bean>) realmCollection;
if (data.isLoaded()) {
Timber.d("Data is already loaded on adapter %s.", adapter);
adapter.updateDataManual(data);
}
if (!data.isValid()) {
Timber.e("Data is not valid.");
}
listener = new RealmChangeListener<RealmResults<Bean>>() {
@Override public void onChange(RealmResults<Bean> newResults) {
Timber.v("Change listener for manual data triggered: %d results in fragment for category %s and adapter %s.",
newResults.size(), category.toString(), adapter);
adapter.updateDataManual(newResults);
}
@Override protected void finalize() throws Throwable {
Timber.d("Finalizing change listener for adapter %s.", adapter);
super.finalize();
}
};
data.addChangeListener(listener);
MyTimer.setRepeatingCallback(() -> {
Timber.v("RealmResults in adapter %s are %s and %s, and the ChangeListener is %s.",
adapter,
data.isValid() ? "valid" : "invalid",
data.isLoaded() ? "loaded" : "not loaded",
listener);
return true;
}, 5000);
}
As you can see, I made efforts to ensure that the query is valid and has not loaded until the change listener is added and that neither the RealmResults
nor the RealmChangeListener
are garbage collected.
Still, out of four RealmChangeListeners
, only two or less (sometimes zero) trigger.
Note that this only happens if the second activity is opened shortly after starting the asynchronous write on the MainActivity. If I wait for 2 seconds, everything works as intended. I did verify that the RealmChangeListener
is not garbage collected, since the finalize()
is called after exiting the app. I have no idea what could prevent the listener from working. Is there anything specific I should pay attention to?
回答1:
You need to have a (strong) field reference to the RealmResults<T>
so that you keep it from getting GC'd.
If a RealmResults gets GC'd, then Realm can no longer auto-update it.
来源:https://stackoverflow.com/questions/41804318/realmchangelistener-does-not-execute-when-added-shortly-after-asynchronous-write