Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

findFirstAsync is not emitting object when queried object is deleted from Realm #3138

Closed
viraj49 opened this issue Jul 5, 2016 · 19 comments · Fixed by #4236
Closed

findFirstAsync is not emitting object when queried object is deleted from Realm #3138

viraj49 opened this issue Jul 5, 2016 · 19 comments · Fixed by #4236
Assignees
Milestone

Comments

@viraj49
Copy link

viraj49 commented Jul 5, 2016

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

@Zhuinden
Copy link
Contributor

Zhuinden commented Jul 5, 2016

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

@viraj49
Copy link
Author

viraj49 commented Jul 5, 2016

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

@Zhuinden
Copy link
Contributor

Zhuinden commented Jul 5, 2016

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.

@viraj49
Copy link
Author

viraj49 commented Jul 5, 2016

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.

@Zhuinden
Copy link
Contributor

Zhuinden commented Jul 6, 2016

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 ?

@cmelchior
Copy link
Contributor

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.

@viraj49
Copy link
Author

viraj49 commented Jul 6, 2016

Thanks

@Zhuinden
Copy link
Contributor

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?

@cmelchior
Copy link
Contributor

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

@cmelchior cmelchior removed this from the 2.0 milestone Oct 10, 2016
@Trinkes
Copy link

Trinkes commented Oct 17, 2016

Any update on this issue?

@Zhuinden
Copy link
Contributor

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

@Trinkes
Copy link

Trinkes commented Oct 17, 2016

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.

@Zhuinden
Copy link
Contributor

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)

@Trinkes
Copy link

Trinkes commented Oct 17, 2016

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

@eikaramba
Copy link

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

@Trinkes
Copy link

Trinkes commented Nov 24, 2016

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.

@Zhuinden
Copy link
Contributor

Zhuinden commented Jan 9, 2017

I still think this makes RealmChangeListener added to RealmObject a bit pointless, so maybe #3834 will force this to work.

@Zhuinden
Copy link
Contributor

Object Store notifications fixed this?

Nice.

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

@cmelchior
Copy link
Contributor

Yes, which also why this is a breaking change

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants