Docs Menu
Docs Home
/ /
Kit de desarrollo de software .NET

Reaccionar a los cambios - SDK .NET

Todos los objetos de Realm son objetos vivos, lo que significa que se actualizan automáticamente cada vez que se modifican. Realm emite un evento de notificación siempre que cambie alguna propiedad.

El sistema de notificaciones de Realm te permite observar y reaccionar ante cambios en tus datos, independientemente de las escrituras que los causaron. Para observar los cambios, crea un controlador de notificaciones para un Realm, una colección administrada o un objeto de Realm que quieras supervisar. Después, puedes agregar la lógica específica de tu aplicación relacionada con el cambio.

Nota

Para obtener información sobre cómo vincular cambios de datos a la interfaz de usuario de su proyecto, consulte Vinculación de datos.

Realm emite tres tipos de notificaciones:

  • Notificaciones de reino cada vez que un reino específico realiza una transacción de escritura.

  • Notificaciones de colección cada vez que se cambia una colección gestionada, como inserciones, actualizaciones y eliminaciones de objetos en la colección.

  • Notificaciones de objetos siempre que cambia un objeto de Realm específico.

Nota

Las notificaciones solo funcionan cuando tu dominio se actualiza regularmente. En el hilo principal o de interfaz de usuario de tu aplicación, las actualizaciones del dominio se realizan automáticamente. En los hilos en segundo plano, debes gestionar esto tú mismo llamando a Realm.Refresh() o instalando un SynchronizationContext.en el hilo antes de abrir el dominio. La biblioteca de terceros Nito.AsyncEx.Context proporciona una SynchronizationContext Implementación y una API conveniente para instalarlo.

Puedes registrar un controlador de notificaciones en todo un dominio. El dominio invoca el controlador de notificaciones cada vez que se confirma una transacción de escritura en ese dominio.

El controlador no recibe información específica sobre el cambio. Esto es útil cuando se desea saber si ha habido un cambio, pero no se necesita saber específicamente qué cambio se ha producido.

Supone que estás creando una aplicación colaborativa en tiempo real y deseas tener un contador que aumente cada vez que se realice un cambio. En este escenario, podrías suscribirte al gestor de notificaciones del realm y añadir el código que controla el indicador.

// Observe realm notifications.
realm.RealmChanged += (sender, eventArgs) =>
{
// The "sender" object is the realm that has changed.
// "eventArgs" is reserved for future use.
// ... update UI ...
};

Puedes observar los cambios en una colección de objetos de dominio y en las propiedades de la colección de dominios de un objeto. Hay dos maneras de recibir notificaciones sobre los cambios en una colección: registrar un controlador de notificaciones en la colección o controlar el evento CollectionChanged.

Puedes registrar un controlador de notificaciones en una colección específica dentro de un dominio. La colección puede estar formada por objetos del dominio (como realm.All<Person>()) o por una propiedad de colección en un objeto del dominio (como house.Owners, donde "Propietarios" es de tipo IList).

El controlador recibe una descripción de los cambios realizados en la colección desde la última notificación. A diferencia de las notificaciones de todo el dominio, las notificaciones de colección contienen información detallada sobre el cambio y proporcionan la información necesaria para administrar una lista u otra vista que represente la colección en la interfaz de usuario.

Realm emite una notificación inicial al añadir una suscripción. Tras la notificación inicial, Realm envía notificaciones asincrónicamente cada vez que una transacción de escritura añade, modifica o elimina objetos de la colección.

La notificación contiene un ChangeSet con 6 propiedades:

  • DeletedIndices es un int[] que contiene los índices de los objetos que fueron eliminados.

  • InsertedIndices es un int[] que contiene los índices de los objetos que se insertaron.

  • ModifiedIndices Es un int[] que contiene los índices antiguos de los objetos modificados. Estos índices indican la posición de los objetos modificados en la colección original antes de cualquier eliminación o inserción.

  • NewModifiedIndices es un int[] que representa las mismas entradas que la propiedad ModifiedIndices, pero los índices representan las nuevas ubicaciones en la colección después de que se hayan contabilizado todos los cambios.

  • IsCleared es un valor booleano establecido en true cuando se ha borrado una colección llamando al método Clear().

  • Moved es una matriz de estructuras ChangeSet.Move que contienen el índice anterior y nuevo de un objeto movido dentro de la colección.

Importante

El orden importa

En los controladores de notificaciones de las colecciones, siempre aplica los cambios en el siguiente orden:

  1. eliminaciones

  2. inserciones

  3. modificaciones

Manejar las inserciones antes de las eliminaciones puede generar un comportamiento inesperado.

Para suscribirse a las notificaciones de recopilación, llame al método SubscribeForNotifications. SubscribeForNotifications devuelve un token de suscripción que se puede eliminar en cualquier momento para dejar de recibir notificaciones sobre la recopilación.

El siguiente código muestra cómo observar una colección en busca de cambios.

// 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.
}
});

El SDK también proporciona una colección KeyPathsCollection, que permite filtrar los campos que activarán una notificación. Se pasa KeyPathsCollection el SubscribeForNotifications método al método. El siguiente código muestra cómo observar campos específicos:

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);

Para anular el registro de un detector de cambios, llame a Dispose en el token. El siguiente código muestra cómo hacerlo:

// 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();

Cada colección INotifyCollectionChanged de Realm implementa, lo que permite usar una colección directamente en escenarios de enlace de datos. Dado que INotifyCollectionChanged las colecciones implementan, otra forma de supervisar los cambios en las colecciones es gestionar el evento CollectionChanged y comprobar el tipo de NotifyCollectionChangedAction.

Importante

Información menos detallada

El controlador de eventos CollectionChanged no proporciona el mismo nivel de detalle sobre los cambios que SubscribeForNotifications.

El siguiente código le muestra cómo implementar el controlador de eventos 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.
}
}

Puedes registrar un controlador de notificaciones en un objeto específico dentro de un dominio para que el SDK te notifique cuando cambie alguna de sus propiedades. El controlador recibe información sobre qué campo ha cambiado. Con el nombre del campo, puedes obtener el nuevo valor.

El siguiente código muestra cómo observar un objeto en busca de cambios.

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();
}

Cuando ya no desee recibir notificaciones sobre un detector de cambios, cancele el registro del controlador. El código es el mismo para una colección de objetos de dominio y una propiedad de colección. El siguiente código muestra cómo cancelar el registro de un detector de cambios en ambos casos:

// 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;

Los cambios en documentos anidados a más de cuatro niveles de profundidad no activan notificaciones de cambio.

Si tiene una estructura de datos en la que necesita escuchar cambios cinco niveles más abajo o más profundos, las soluciones alternativas incluyen:

  • Refactorice el esquema para reducir la anidación.

  • Agregue algo como "push-to-refresh" para permitir que los usuarios actualicen los datos manualmente.

Volver

Transacciones

En esta página