React 变更 - .NET SDK
在此页面上
所有Realm对象都是活动对象,这意味着它们在修改时会自动更新。 每当任何属性发生变化时, Realm都会发出通知事件。
Realm 的通知系统允许您监视数据更改并做出 React,而与导致更改的写入无关。要观察更改,您可以为要观察的 Realm、托管集合或 Realm 对象创建通知处理程序。 然后,您可以添加与更改相关的特定应用逻辑。
注意
有关将数据更改绑定到项目中的用户界面的信息,请参阅数据绑定。
Realm 会发出三种通知:
每当特定 Realm 提交写事务时,Realm 都会收到 Realm 通知。
每当托管集合发生任何更改时(例如插入、更新和删除集合中的对象),都会收到集合通知。
每当特定 Realm 对象发生更改时,都会收到对象通知。
注意
通知仅在域定期刷新时才起作用。在应用程序的主线程或用户界面线程中, 域刷新会自动发生。在背景线程上,您需要自行处理此问题,方法是调用 Realm.Refresh() 或安装 SynchronizationContext 在打开域之前在线程上。第三方库 Nito.AsyncEx.Context 提供了SynchronizationContext
实施以及用于安装该实现的便捷API 。
注册 Realm 变更监听器
您可以在整个 Realm 上注册通知处理程序。 每当提交该 域 上的任何写事务(write transaction)时,Realm 都会调用通知处理程序。
处理程序不会收到有关变更的特定信息。 当您想知道是否有更改但不需要具体知道发生了什么更改时,此功能非常有用。
假设您正在构建一个实时协作应用程序,并且希望有一个计数器在每次进行更改时都会增加。 在这种情况下,您可以订阅域通知处理程序并添加控制该指标的代码。
// Observe realm notifications. realm.RealmChanged += (sender, eventArgs) => { // The "sender" object is the realm that has changed. // "eventArgs" is reserved for future use. // ... update UI ... };
注意collection更改
您可以监视 Realm 对象集合以及对象上 Realm集合属性的更改。 有两种方法可以获得有关集合变更的通知:在集合上注册通知处理程序或处理 CollectionChanged 事件。
您可以在特定的collection中的域上注册通知处理程序。该collection可以是 Realm 对象(例如realm.All<Person>()
),也可以是 Realm 对象上的属性(例如house.Owners
,其中 "Owners" 的类型为IList
)。
处理程序接收自上次通知以来对collection所做更改的描述。与 Realm 范围的通知不同,集合通知包含有关更改的详细信息,并提供管理用户界面中表示集合的列表或其他视图所需的信息。
添加订阅时,Realm 会发出初始通知。 在初始通知之后,每当写事务(write transaction)添加、修改或删除collection中的对象时,Realm 都会异步传递通知。
通知变更集
通知包含一个具有6属性的ChangeSet :
DeletedIndices
是一个int[]
,其中包含已删除对象的索引。InsertedIndices
是一个int[]
,其中包含已插入对象的索引。ModifiedIndices
是一个int[]
,其中包含已修改对象的旧索引。 这些索引指示在发生任何删除或插入操作之前,已修改对象在原始集合中的位置。NewModifiedIndices
是一个int[]
ModifiedIndices
,表示与属性相同的条目,但索引表示考虑所有更改后collection中的新位置。IsCleared
是一个布尔值,当通过调用Clear()
方法清除collection时,该值设置为true
。Moved
是一个ChangeSet.Move结构体数组,其中包含在集合中移动的对象的上一个索引和新索引。
重要
顺序很重要
在collection通知处理程序中,始终按以下顺序应用更改:
删除
插入
修改
在删除操作之前处理插入操作可能会导致意外行为。
获取所有集合更改的通知
若要订阅集合通知,请调用SubscribeForNotifications方法。 SubscribeForNotifications
返回一个订阅令牌,可随时处理该令牌以停止接收有关集合的通知。
以下代码演示了如何观察collection的更改。
// Watch for collection notifications. var subscriptionToken = realm.All<Dog>() .SubscribeForNotifications((sender, changes) => { if (changes == null) { // This is the case when the notification is called // for the first time. // Populate tableview/listview with all the items // from `collection` return; } // Handle individual changes foreach (var i in changes.DeletedIndices) { // ... handle deletions ... } foreach (var i in changes.InsertedIndices) { // ... handle insertions ... } foreach (var i in changes.NewModifiedIndices) { // ... handle modifications ... } if (changes.IsCleared) { // A special case if the collection has been cleared: // i.e., all items have been deleted by calling // the Clear() method. } });
限制通知
SDK 还提供了KeyPathsCollection ,它提供了一种过滤将trigger通知的字段的方法。 您将KeyPathsCollection
传递给SubscribeForNotifications
方法。 以下代码展示了如何观察特定字段:
var query = realm.All<Person>(); KeyPathsCollection kpc; // Use one of these equivalent declarations to // specify the fields you want to monitor for changes: kpc = KeyPathsCollection.Of("Email", "Name"); kpc = new List<KeyPath> {"Email", "Name"}; // To get all notifications for top-level properties // and 4 nested levels of properties, use the `Full` // static value: kpc = KeyPathsCollection.Full; // To receive notifications for changes to the // collection only and none of the properties, // use the `Shallow` static value: kpc = KeyPathsCollection.Shallow; query.SubscribeForNotifications(notificationCallback, kpc);
取消注册变更监听器
要取消注册变更侦听器,请对令牌调用Dispose
。 以下代码演示了如何执行此操作:
// Watch for collection notifications. // Call Dispose() when you are done observing the // collection. var token = realm.All<Dog>() .SubscribeForNotifications((sender, changes) => { // etc. }); // When you no longer want to receive notifications: token.Dispose();
处理 CollectionChanged 事件
每个 Realm 集合都实现了INotifyCollectionChanged
,这允许您直接在数据绑定场景中使用集合。 由于集合实现了INotifyCollectionChanged
,因此监控集合更改的另一种方法是处理 CollectionChanged 事件,并检查 NotifyCollectionChangedAction 的类型。
重要
不太详细的信息
CollectionChanged
事件处理程序提供的更改详细信息级别与SubscribeForNotifications
不同。
以下代码向您展示如何实施CollectionChanged
事件处理程序:
{ // Subscribe to a query realm.All<Dog>().AsRealmCollection().CollectionChanged += HandleCollectionChanged; // Subscribe to a property collection gracie.Owners.AsRealmCollection().CollectionChanged += HandleCollectionChanged; ... } private void HandleCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e) { // Use e.Action to get the // NotifyCollectionChangedAction type. if (e.Action == NotifyCollectionChangedAction.Add) { // etc. } }
注册对象变更侦听器
您可以在 域 中的特定对象上注册通知处理程序,以便 SDK 在对象的任何属性发生更改时通知您。处理程序接收有关哪个字段已更改的信息。 通过字段名称,您可以获取新值。
以下代码演示了如何观察对象的更改。
var artist = realm.All<Person>() .FirstOrDefault(p => p.Name == "Elvis Presley"); artist.PropertyChanged += (sender, eventArgs) => { var changedProperty = eventArgs.PropertyName!; Debug.WriteLine( $@"New value set for 'artist': '{changedProperty}' is now {artist.GetType() .GetProperty(changedProperty).GetValue(artist)}"); }; realm.Write(() => { artist.Name = "Elvis Costello"; }); realm.Refresh(); }
取消注册变更监听器
当您不想再接收有关变更侦听器的通知时,可以取消注册处理程序。 对于 Realm 对象集合和集合属性,该代码是相同的。 以下代码展示了如何在两者上取消注册变更侦听器:
// Unsubscribe from notifications on a // realm listener realm.RealmChanged -= OnRealmChanged; // Unsubscribe from notifications on a // collection of realm objects realm.All<Item>().AsRealmCollection() .CollectionChanged -= OnItemsChangedHandler; // Unsubscribe from notifications on a // collection property items.AsRealmCollection().CollectionChanged -= OnItemsChangedHandler;
变更通知限制
嵌套文档中深度超过四级的变更不会触发变更通知。
如果您的数据结构需要侦听第五层深度或更深层的更改,解决方法包括:
重构模式以减少嵌套。
添加“推送以刷新”一类的内容,使用户能够手动刷新数据。