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

Finegrained notifications #989

Closed
Trikke opened this issue Mar 26, 2015 · 49 comments
Closed

Finegrained notifications #989

Trikke opened this issue Mar 26, 2015 · 49 comments
Assignees
Milestone

Comments

@Trikke
Copy link

Trikke commented Mar 26, 2015

Hi Realm devs,

we now have the RealmChangeListener to listen for changes if some background thread updates the Realm instance, which is great. But i'd like to put a feature request forward for more fine grained control when a listener can be called. It would be nice if it were possible to add a RealmChangeListener that only fires if a certain class of RealmObject is updated.

The issue i have now is that i have multiple fragments for multiple classes of RealmObject (eg. RealmUser, RealmMessage, RealmBeer) open at once, then a background services updates one of the RealmUser instances. Now all the RealmChangeListener are fired, and all fragments are updated individually. While ideally only the one that deals with RealmUser should be updating.

@cmelchior
Copy link
Contributor

Hi @Trikke
Yes. more finegrained notifications are also very high on our priority list, and we already have someone working on it. Unfortunately it require some changes to the core database, but you will hopefully see some progress on this soon.

@cmelchior cmelchior changed the title Feature request : Changelistener for RealmObject Feature request : Finegrained notifications Mar 27, 2015
@cmelchior cmelchior added P1 Blocked This issue is blocked by another issue T-Enhancement labels Mar 27, 2015
@ghost
Copy link

ghost commented Mar 31, 2015

Hi @cmelchior

Will this enhancement also include some sort of support for adding RealmChangeListeners to RealmResults<> as well and get notifications when a RealmObject referenced by the RealmResults<> gets updated?

This would be a very useful feature and would surely improve the performance of RealmBaseAdapter.
For instance the number of draw calls/redraws to a bound ListView would be vastly reduced.

Thanks in advance,
Dimitris.

PS. Is there a roadmap or expected release date for this feature?

@cmelchior cmelchior changed the title Feature request : Finegrained notifications Finegrained notifications Apr 15, 2015
@rynti
Copy link

rynti commented May 18, 2015

+1

1 similar comment
@treylon
Copy link

treylon commented May 18, 2015

+1

@bdbergeron
Copy link

I'm also anxiously awaiting this feature. In my opinion, this is definitely one of the features that needs to be implemented before a 1.0 release!

@yolapop
Copy link

yolapop commented Aug 1, 2015

I'm also excited with this feature 👍

Btw @feugatos, can you explain what you mean by this?

This would be a very useful feature and would surely improve the performance of RealmBaseAdapter. For instance the number of draw calls/redraws to a bound ListView would be vastly reduced.

@beeender
Copy link
Contributor

Comments from #1378 by mshusek.

When we use RecyclerView or we want reload view under certain conditions default onChange is not sufficient. Now, in RecyclerView we have to reload visible rows so it is not a optimal solution. Moreover, we can not use animation when item is delete or insert to our model.

I think better sollution will be implementing something like that:

 ContentObserver.ModelChangeListener() 
{
    @Override
    public void onModelChanged() { 
    } 
    @Override
    public void onModelUpdated(Object obj) {
    }
    @Override
    public void onModelDeleted(Object obj) {
    }
    @Override
    public void onModelInserted(Object obj) {
    }
};

@gpulido
Copy link

gpulido commented Aug 28, 2015

Another +1 for have this feature implemented.
Alongside with a RealmAdapter for recyclerviews those will be an amazing plus to an already great library!

@cmelchior
Copy link
Contributor

Work-in-progress API proposal:

Design criteria:

  • Minimize number of classes
  • Reuse existing concepts
  • Everything should be observable

Open questions

  • Should closing a Realm trigger a onChange?
//
// Realm API
//

RealmChangeListener listener = new RealmChangeListener() {
  @Override
  public void onChange() {
    // change detected
  }
}

// Realms
realm.addChangeListener(listener);

// Query results
RealmResult<Foo> results = realm.allObjects(Foo.class);
results.addChangeListener(listener);

// Lists
RealmList<Bar> list = realm.where(Foo.class).findFirst().getBarList();
list.addChangeListener(listener);

// Objects
// Note: This will only work if we keep a RealmObject base class which is debatele. 
Foo obj = realm.where(Foo.class).findFirst(); 
obj.addChangeListener(listener);

// Alternative object listener
realm.addChangeListener(obj, listener);

// KVO support, i.e. observing on individual properties
String keyPath = "fieldName"; // Name of field
keyPath = "bar.childField"; // Name of child field
keyPath = "bar[0]"; // What about RealmList entries?

// Option 1
obj.addChangeListener(keyPath, new RealmPropertyChangeListener() {
  @Override
  public void onChange(Object oldValue, Object newValue) {
    // Types is an issue.
  }
});

// Option 2
obj.addChangeListener(keyPath, new RealmChangeListener() {
  @Override
  public void onChange() {
    // Has to ask for the value. No access to the previous value.
  }
});

//
// RecyclerView.Adapter
//
// Enabling animations in the RecyclerViewAdapter also means we need to support information
// about how things has changed in RealmResults/RealmList

notifyItemChanged(int position)
notifyItemChanged(int position, Object payload)
notifyItemInserted(int position)
notifyItemMoved(int fromPosition, int toPosition)
notifyItemRangeChanged(int positionStart, int itemCount)
notifyItemRangeChanged(int positionStart, int itemCount, Object payload)
notifyItemRangeInserted(int positionStart, int itemCount)
notifyItemRangeRemoved(int positionStart, int itemCount)
notifyItemRemoved(int position)

@beeender
Copy link
Contributor

beeender commented Sep 1, 2015

@cmelchior Any use case for "Should closing a Realm trigger a onChange?"

@cmelchior
Copy link
Contributor

Yes, like removing references to objects that would otherwise crash or to reset UI state.

@yaming116
Copy link

@cmelchior Whether you can provide database changes, tell me which table changed。

RealmChangeListener listener = new RealmChangeListener() {
  @Override
  public void onChange(Class changeClass) {
    // change detected
  }
}

@waltarmour
Copy link

Yes, I would definitely like to see a way to catch changes to specific classes of objects. However, I'm not sure about the exact signature from @yaming116 . What happens when a single transaction changes multiple classes? Would we get several simultaneous onChange() calls? Maybe, if this approach was used, it could be a Class[] or something to allow for a single invocation.

Of course, the desired behaviour could be synthesized using the query results change listener but that seems a bit hacky at first glance. Not sure in the long run.

@dadino
Copy link

dadino commented Oct 9, 2015

@waltarmour @cmelchior it could be something like this.

RealmChangeListener listener = new RealmChangeListener(Class[] classes) {
  @Override
  public void onChange() {
      // change detected
  }
}

Or something much more precise, using PrimaryKey (but it may be too much):

class ChangedClass{
    Class class;
    ChangedEntity[] entities;
}

class ChangedEntity{
    Object primaryKeys;
    int change; //created, updated, deleted
}

RealmChangeListener listener = new RealmChangeListener(Class[] classes) {
  @Override
  public void onChange(ChangedClass[] changed) {
      // change detected
  }
}

With this one the RecyclerView animations should be easy. I don't know how it could work without a PrimaryKey.

Also, don't use RealmList/RealmResult/RealmObject .addChangeListener(). Use realm.addChangeListener(RealmList/RealmResult/RealmObject, listener) instead and get the needed classes for the listener from the first parameter.

@Teja-Konjeti
Copy link

Teja-Konjeti commented Nov 26, 2016

@cmelchior Will something similar to Realm Xamarin Fine Notifications be implemented soon? Any ETA? That feature on Xamarin Platform is exactly the one needed. Right now updating the Recycler View and writing my own code for finding which row got updated is getting very cumbersome for me which is the reason I am looking to migrate to Realm. Do provide me with an ETA. Thanks! :)

Edit: I just checked and all the other Realm platforms have the fine grained notifications except for Java. Hope it will be implemented soon.

@Zhuinden
Copy link
Contributor

@Sai-Teja Collection Notifications depend on #3834 which were started a few days ago, so it's bound to happen

@Teja-Konjeti
Copy link

Teja-Konjeti commented Nov 27, 2016

@cmelchior I mean this request is one of the most important reasons people use orms. It has been put up for one and a half year now. This is there in all the other platforms of Realm and it is the basic feature which should have been there before the release of v1.0 and now this library is in 2.2 I would prefer to know the ETA of this feature as this is why I want to use orm other than SQLite other wise I might use some other ORM. So, do comment if you can specify an ETA.
Nd @Zhuinden The third comment in #3834 is saying something else anyways if you can do give an ETA! :)

@Zhuinden
Copy link
Contributor

Zhuinden commented Nov 27, 2016

@Sai-Teja that comment is responding to me, that "no, that is a different problem". Although I still think that might fix those issues in one go 👅

The object store integration is a complex thing. It will be done eventually.

I am not actually working on it so I do not know the exact ETA.

@cmelchior
Copy link
Contributor

@Sai-Teja To my knowledge, no ORM provide fine-grained notifications to the level described in this issue. "Table"-based notifications (some object of type A changed) are supported by e.g SQLBrite (and possibly others), but Realm also has support for that.

This issue is for tracking changes to collections (added/removed/moved) + changes to single objects (fields changed). If you are looking for support for that today, DiffUtil (https://developer.android.com/reference/android/support/v7/util/DiffUtil.html) can be used for the collection changes no matter what DB solution you use.

Regarding ETA. All I can say is that we are working actively on this, but we don't have a timeline we can share yet.

@Teja-Konjeti
Copy link

@cmelchior I just wanted to correct "no ORM provide fine-grained notifications to the level described in this issue"
DBFlow has finegrained notifications so I'm going for it now!
I'll watch this thread for updates then!
I'm not against realm It's just this is the main feature I'm looking for! :)

@evgeny-sureev
Copy link

@cmelchior Realm Swift provides such fine-grained notifications on collections and on single objects via KVO: https://realm.io/docs/swift/latest/#notifications

@Zhuinden
Copy link
Contributor

Zhuinden commented Dec 9, 2016

@evgeny-sureev Realm Java depends on #3834 to add fine-grained notifications

@eygraber
Copy link

eygraber commented Feb 3, 2017

Has an API been decided for this yet? Will it look something like ListUpdateCallback`?

@cmelchior
Copy link
Contributor

@eygraber There is a proposal in #3977 . Right now it is closer to the API from RecyclerView, but it doesn't seem much different from what you linked either. We are still looking for feedback, so if you have a use case not covered in #3977 we would love to hear about it.

beeender added a commit that referenced this issue Feb 17, 2017
- Add RealmObservable and RealmCollectionObservable interfaces.
- Enable detailed change information for RealmResults through
  OrderedCollectionChange interface.
- Fix a bug in the ObserverPairList which could cause the removed
  listener gets called if it was removed during previous listener
  iteration.

Fix #989
beeender added a commit that referenced this issue Feb 20, 2017
- Add RealmObservable and RealmCollectionObservable interfaces.
- Enable detailed change information for RealmResults through
  OrderedCollectionChange interface.
- Fix a bug in the ObserverPairList which could cause the removed
  listener gets called if it was removed during previous listener
  iteration.

Fix #989
beeender added a commit that referenced this issue Feb 20, 2017
- Add RealmObservable and RealmCollectionObservable interfaces.
- Enable detailed change information for RealmResults through
  OrderedCollectionChange interface.
- Fix a bug in the ObserverPairList which could cause the removed
  listener gets called if it was removed during previous listener
  iteration.

Fix #989
@beeender beeender self-assigned this Feb 20, 2017
beeender added a commit that referenced this issue Feb 23, 2017
- Add RealmObservable and RealmCollectionObservable interfaces.
- Enable detailed change information for RealmResults through
  OrderedCollectionChange interface.
- Fix a bug in the ObserverPairList which could cause the removed
  listener gets called if it was removed during previous listener
  iteration.

Fix #989
@beeender
Copy link
Contributor

For anyone who may want to try this feature before we release it:
The PR #4191 to enable this feature has been merged, the snapshot will be available in a few hours which will include this feature as well.
For how to use the fine grained notification with recycler view, see sample code here https://github.com/realm/realm-android-adapters/pull/83/files#diff-5db60168121b71f755fdff3c780e4c3dR56 .

The listeners on RealmList will be available in the next release as well. See #4216 .

The next release won't have fine grained notification for the object level. That has been tracked by another issue #4101 .

Feel free to open a new issue if you meet problems when trying it with snapshot.

Thanks for all your patience.

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

No branches or pull requests