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

Changed Notification raised even when the value is the same #5451

Open
gpulido opened this issue Oct 23, 2017 · 15 comments
Open

Changed Notification raised even when the value is the same #5451

gpulido opened this issue Oct 23, 2017 · 15 comments

Comments

@gpulido
Copy link

gpulido commented Oct 23, 2017

I have a RealmObject with a private property with get / set accesor.

public class Dog extends RealmObject
{
	private String name;
	public String getName()
	{
		return name;
	}
	
	public void setName(String name)
	{
		this.name = name;
	}
}

(Nothing fancy there).
I have a subscritor to a list of dogs:

RealmResults<Dog> mydogs = realm.where(Dog.class).findAll();
mydogs.addChangeListener((dogs, changeSet) -> //any update stuff);

As expected, anytime the name of any dog is changed the listener is hit, however what I didn't expect is that the listener is hit everytime I assign a name to the name field even if it is the same as it has, I don't know if this behavior is by design, so I had to add something like this:

       public void setName(String name)
	{
                if (!this.name.equals(name)
		     this.name = name;
	}

I know that this is an easy solution, but I wonder why the listener is launched even if the underlined data is not changed.
Is this the expected behavior?
(I'm using Realm 4.1.0 on a 6.0 Android emulated device)

@beeender
Copy link
Contributor

Yes, this is by design. The checking can be moved to the Realm side so you don't have to do it every time. But that may slow down other cases since for every setters Realm will do a equality check. I am not quite sure we will change the design.

So for now, i think you still need to do the check in your setters manually.

@gpulido
Copy link
Author

gpulido commented Oct 23, 2017

I understand that to make checks every time is expensive, but it is a bit "unnatural" to receive notifications when they are not expected.
The problem is that sometimes to process the notification logic is even more expensive, in my case I'm refreshing a view. I could try to manage the check logic on the notification, to review if anything has really changed on the changeset, but the problem is that as the RealmResults already have the last values, so I can't compare before applying the changes.
Being said that, I will just add the setters checks on those fields that could be problematic in my case.
However this would prevent me to use a direct use of the property without a setter, and I wonder if it would affect it in Kotlin (I'm start to think on moving my base code to kotlin)

@cmelchior
Copy link
Contributor

Having a custom setter doesn't effect Realm as long as the standard getter is still there. See https://medium.com/@nomanr/backing-field-in-kotlin-explained-9f903f27946c

We have an issue discussing what to do about the situation as it isn't entirely trivial. Not receiving updates about overriding the same field makes sense for UI components, but might be relevant in other cases. If I can just remember where we had that discussion 🙄

@Zhuinden
Copy link
Contributor

Zhuinden commented Oct 23, 2017

See realm/realm-core#2787 for a discussion of this on Realm Core level.

So this means that you get notification because a set operation is logged by Core which is indeed a requirement not to miss changes in a synchronized setting.

Which is why only the user knows if "not setting the value" is not necessary.

@gpulido
Copy link
Author

gpulido commented Oct 24, 2017

Thanks for the insight about the current status. From that thread, It seems that the decision have been made more for a technical problem, as even in the discussion is stated that it strange to receive notifications even when there is not change made.
The problem with the "only the user knows" approach is that, for example, I have more than 30 classes on my model and there are a lot of properties to check and that could be cumbersome to add all the guards just to make my code to behave the "expected way" from the user point of view. Also the other approach would be to "check" when the notification is received, but again as realm has the latest changes already "loaded" on my collection I don't have the data to compare if the field values are the same or not.
Just to be clear, I'm not complaining, realm is amazing and you guys are doing and great work and this
is a tricky situation and I guess one of the payloads of using sync.

Thank you for taking the time to find and post the thread discussion.

@Zhuinden
Copy link
Contributor

It is indeed tricky unfortunately, personally I was wondering about the possibility of creating some kind of generated "merge" method that only calls the setter if it's not equal. But then you'd have another new method to save a RealmObject, there are already 3 of them :D

@nhachicha
Copy link
Collaborator

I think any elegant solution will probably be implemented at Core level (to have old/new value) this requires stable ID work to be completed first realm/realm-core#1971

@Zhuinden
Copy link
Contributor

Zhuinden commented Nov 8, 2017

@nhachicha Row-level stable IDs? that'll take a while 😄 I'm not even sure if Realm-Java has stable ID support for table in non-sync mode

@pankajsoni19
Copy link

We are using realm extensively in quite a number of projects both in java & swift. While swift object change has new/old value support. In android we would like something along those lines if possible.

@Zhuinden
Copy link
Contributor

@softwarejoint you should bring that to #4366

@digitalhoax
Copy link

+1 for a way to get notified of actual changes of the model. The update functionality is great because it saves a lot of code that is boilerplate, but if there is no way of knowing whether it modified the model, we can not use it to update views. In our case we query our server every second for a JSON of the model. I would love to just refresh the view in the on change notification but it will trigger every second regardless of changes to the JSON from the server.

@NikKovIos
Copy link

Here is my case of that problem with gif:

  1. I fetch existing in realm data an show it.
  2. Load new data from the server.
  3. It comes the SAME data, but the realm still sends modification changes in it's notification.
    Because of that the tableView jumps up, when the data return from the server and notification block fired.
    glitch

@Zhuinden
Copy link
Contributor

You can use the new ImportFlags to change this behavior

@NikKovIos
Copy link

Does it have the analog in swift?

@Zhuinden
Copy link
Contributor

All I know is that it was merged in Java here #6224

I don't see anything similar on realm-cocoa which is odd.

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

No branches or pull requests

9 participants