Docs 菜单
Docs 主页
/ /
Atlas Device SDKs
/

React 变更 - .NET SDK

在此页面上

  • 注册 Realm 变更监听器
  • 注意collection更改
  • 通知变更集
  • 获取所有集合更改的通知
  • 限制通知
  • 取消注册变更监听器
  • 处理 CollectionChanged 事件
  • 注册对象变更侦听器
  • 取消注册变更监听器
  • 变更通知限制

所有Realm对象都是活动对象,这意味着它们在修改时会自动更新。 每当任何属性发生变化时, Realm都会发出通知事件

Realm 的通知系统允许您监视数据更改并做出 React,而与导致更改的写入无关。要观察更改,您可以为要观察的 Realm、托管集合或 Realm 对象创建通知处理程序。 然后,您可以添加与更改相关的特定应用逻辑。

注意

有关将数据更改绑定到项目中的用户界面的信息,请参阅数据绑定。

Realm 会发出三种通知:

  • 每当特定 Realm 提交写事务时,Realm 都会收到 Realm 通知

  • 每当托管集合发生任何更改时(例如插入、更新和删除集合中的对象),都会收到集合通知

  • 每当特定 Realm 对象发生更改时,都会收到对象通知

注意

通知仅在域定期刷新时才起作用。在应用程序的主线程或用户界面线程中, 域刷新会自动发生。在背景线程上,您需要自行处理此问题,方法是调用 Realm.Refresh() 或安装 SynchronizationContext 在打开域之前在线程上。第三方库 Nito.AsyncEx.Context 提供了SynchronizationContext 实施以及用于安装该实现的便捷API 。

您可以在整个 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 ...
};

您可以监视 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通知处理程序中,始终按以下顺序应用更改:

  1. 删除

  2. 插入

  3. 修改

在删除操作之前处理插入操作可能会导致意外行为。

若要订阅集合通知,请调用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();

每个 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;

嵌套文档中深度超过四级的变更不会触发变更通知。

如果您的数据结构需要侦听第五层深度或更深层的更改,解决方法包括:

  • 重构模式以减少嵌套。

  • 添加“推送以刷新”一类的内容,使用户能够手动刷新数据。

后退

事务