Realm-java: findFirstAsync is not emitting object when queried object is deleted from Realm

Created on 5 Jul 2016  路  19Comments  路  Source: realm/realm-java

Goal

Receive emitted object in following code when RealmObject is deleted from Realm.

realm.where(GitHubUserProfile.class)
         .equalTo("login", login)
         .findFirstAsync()
         .asObservable()

Expected Results

Want to receive a callback when Queried RealmObject is deleted from Realm, just like we do when RealmObject gets modified. I am getting a callback when I use findAllAsync() even when object is deleted.

Actual Results

Not getting a callback when RealmObject is deleted from Realm.

Code Sample

/* Realm NOT emitting when I delete the queried object */
private void sampleQuery1(String login) {
    realm.where(GitHubUserProfile.class)
             .equalTo("login", login)
             .findFirstAsync()
             .asObservable()
             .cast(GitHubUserProfile.class)
             .filter(realmObject -> realmObject.isLoaded())
             .filter(realmObject -> realmObject.isValid())
             .subscribeOn(AndroidSchedulers.mainThread())
             .observeOn(AndroidSchedulers.mainThread())
             .subscribe(gitHubUserProfile -> {
                  view.setData(gitHubUserProfile);
              });
}

/* Realm emitting when I delete the queried object */
private void sampleQuery2(String login) {
    realm.where(GitHubUserProfile.class)
             .equalTo("login", login)
             .findAllAsync()
             .asObservable()
             .cast(GitHubUserProfile.class)
             .filter(realmObject -> realmObject.isLoaded())
             .filter(realmObject -> realmObject.isValid())
             .subscribeOn(AndroidSchedulers.mainThread())
             .observeOn(AndroidSchedulers.mainThread())
             .subscribe(gitHubUserProfile -> {
                  view.setData(gitHubUserProfile);
              });
}

public void clearGitHubUserProfileFromRealm(String login) {
    GitHubUserProfile gitHubUserProfile = realm.where(GitHubUserProfile.class)
        .equalTo("login", login)
        .findFirst();

    Realm realm = Realm.getDefaultInstance();
    if (gitHubUserProfile != null) {
        realm.executeTransaction(realm1 -> gitHubUserProfile.deleteFromRealm());
    }
    realm.close();
}

Version of Realm and tooling

Realm version(s): 1.1.0

Android Studio version: 2.1.2

Which Android version and device: 6.0.1, One plus One

Breaking T-Enhancement

All 19 comments

I think the filter .filter(realmObject -> realmObject.isValid()) eats the deleted objects.

I verified it by putting Logs in .filter(realmObject -> realmObject.isValid()) but it did not reach there.

Technically even if you DID get the deleted object back here, it would no longer exist in the Realm, which means accessing any of its properties would throw an IllegalStateException.

Agreed, I am interested in the notification/callback and not in the object, based on that notification I can either get a fresh object from Network or close the view.

Hmm.. I personally would expect it to work like a RealmChangeListener and give you a new notification each time the underlying Realm changes, but it also returns an Observable<RealmObject> which means it wouldn't make much sense for you to receive invalid objects - I do wonder if isLoaded() filters it out, too (considering you can't really load a deleted object, I'd think).

Can you try removing isLoaded() and isValid() check and change findFirstAsync() to findFirst() to see if that works as you expect?

I'm not too knowledgeable about the inner workings of the Rx support of Realm, so I think this might be over my scope. You will probably need to supply a minimal sample to show what you want to do and why it doesn't work, and send it to help[at]realm.io

@cmelchior ?

Right now we do not trigger change listeners on deleted objects : https://github.com/realm/realm-java/blob/master/realm/realm-library/src/main/java/io/realm/HandlerController.java#L361-Lundefined

But since we are returning "future"-like objects for our async queries, I could be convinced that they should also trigger change listeners when deleted. It would fit the pattern.

However currently that would be a breaking change, so it will unfortunately have to wait for 2.0.

For now the solution would be to use findAllAsync() instead and check on the size of the RealmResults.

Thanks

It seems odd that you wouldn't receive a notification that the element was deleted - because in that case, how could you update the UI to reflect that the item is no longer valid and should not be accessed?

Yes. We intend to change that. I agree that deleting also constitute a change.

Any update on this issue?

@Trinkes in the meantime, this is why I always use RealmResults<T> with RealmChangeListener, even when there's only 1 object

Yah, but the performance is not that good. you have to iterate all objects to check if it's the one you want. Even if you do it in a worker thread, if your table change often, it can be a problem.

You don't have to iterate the list, you just define the query so that you obtain the results with one element (query by ID)

That was clever. It should solve my problem. Thanks!

So with latest realm(2.2.1) is it possible to get notified about deleted entities? We didn't found a way....

As @Zhuinden said, you can get it as a list (even using a query to an object) and if the list size is 0, the item doesn't exits anymore.

I still think this makes RealmChangeListener added to RealmObject a bit pointless, so maybe https://github.com/realm/realm-java/pull/3834 will force this to work.

Object Store notifications fixed this?

Nice.

But that means you need to do a if(obj.isValid()) { check in the RealmObject RealmChangeListener.

Yes, which also why this is a breaking change

Was this page helpful?
0 / 5 - 0 ratings