Todos los objetos de Realm son activos, lo que significa que se actualizan automáticamente al modificarse. Realm emite un evento de notificación cada vez que cambia una propiedad. Puedes registrar un controlador de notificaciones para que detecte estos eventos y actualice tu interfaz de usuario con los datos más recientes.
Registrar un detector de cambios de objetos
Puedes registrar un controlador de notificaciones en un objeto específico dentro de un dominio. El dominio notifica a tu controlador:
Cuando el objeto se borra.
Cuando cambia cualquiera de las propiedades del objeto.
auto token = object.observe([&](auto&& change) { ... }
El manejador recibe un Objetoobject_change que contiene información sobre los cambios, como si el objeto se eliminó. Puede incluir una lista de objetos PropertyChange que contienen información sobre los campos modificados, sus nuevos valores (excepto en las propiedades de lista) y, posiblemente, sus valores anteriores.
if (change.error) { rethrow_exception(change.error); } if (change.is_deleted) { std::cout << "The object was deleted.\n"; } else { for (auto& propertyChange : change.property_changes) { std::cout << "The object's " << propertyChange.name << " property has changed.\n"; auto newPropertyValue = std::get<std::string>(*propertyChange.new_value); std::cout << "The new value is " << newPropertyValue << "\n"; } }
Cuando realice cambios, actualice() el reino para emitir una notificación.
auto config = realm::db_config(); auto realm = realm::db(std::move(config)); // Create an object and move it into the database. auto dog = realm::Dog{.name = "Max"}; realm.write([&] { realm.add(std::move(dog)); }); auto dogs = realm.objects<realm::Dog>(); auto specificDog = dogs[0]; // Set up the listener & observe object notifications. auto token = specificDog.observe([&](auto&& change) { try { if (change.error) { rethrow_exception(change.error); } if (change.is_deleted) { std::cout << "The object was deleted.\n"; } else { for (auto& propertyChange : change.property_changes) { std::cout << "The object's " << propertyChange.name << " property has changed.\n"; auto newPropertyValue = std::get<std::string>(*propertyChange.new_value); std::cout << "The new value is " << newPropertyValue << "\n"; } } } catch (std::exception const& e) { std::cerr << "Error: " << e.what() << "\n"; } }); // Update the dog's name to see the effect. realm.write([&] { specificDog.name = "Wolfie"; }); // Deleting the object triggers a delete notification. realm.write([&] { realm.remove(specificDog); }); // Refresh the database after the change to trigger the notification. realm.refresh(); // Unregister the token when done observing. token.unregister();
Registrar un oyente de cambios de colección
Puede registrar un controlador de notificaciones en una colección. Una colección es una propiedad de lista, mapa o conjunto que puede contener cualquier tipo de datos compatible, incluyendo primitivos u otros objetos.
Realm notifica a su controlador cada vez que una transacción de escritura elimina, agrega o cambia objetos en la colección.
Las notificaciones describen los cambios desde la notificación anterior con tres listas de índices: los índices de los objetos que se eliminaron, insertaron y modificaron.
Importante
El orden importa
En los controladores de notificaciones de colecciones, aplique siempre los cambios en el siguiente orden: eliminaciones, inserciones y modificaciones. Gestionar las inserciones antes de las eliminaciones puede provocar un comportamiento inesperado.
Las notificaciones de colección proporcionan una estructura collection_change que informa el índice de los objetos eliminados, añadidos o modificados. También pueden notificarle si la colección se eliminó.
En este ejemplo, el Person El objeto tiene una lista de Dog objetos como propiedad:
struct Person { std::string name; std::vector<Dog*> dogs; }; REALM_SCHEMA(Person, name, dogs)
Remover un perro, agregar un perro nuevo o modificar un perro activar el manejador de notificaciones:
// Set up the listener & observe a collection. auto token = person.dogs.observe([&](auto&& changes) { if (changes.collection_root_was_deleted) { std::cout << "The collection was deleted.\n"; } else { // Handle deletions, then insertions, then modifications. for (auto& collectionChange : changes.deletions) { std::cout << "The object at index " << std::to_string(collectionChange) << " was removed\n"; } for (auto& collectionChange : changes.insertions) { std::cout << "The object at index " << std::to_string(collectionChange) << " was inserted\n"; } for (auto& collectionChange : changes.modifications) { std::cout << "The object at index " << std::to_string(collectionChange) << " was modified\n"; } } }); // Remove an object from the collection, and then add an object to see // deletions and insertions. realm.write([&] { person.dogs.clear(); person.dogs.push_back(&dog2); }); // Modify an object to see a modification. realm.write([&] { dog2.age = 2; }); // Refresh the realm after the change to trigger the notification. realm.refresh(); // Unregister the token when done observing. token.unregister();
Registrar un oyente de cambios en la colección de resultados
Puede registrar un controlador de notificaciones en una colección de resultados.
Realm notifica a su controlador cada vez que una transacción de escritura elimina, agrega o cambia objetos en la colección.
Las notificaciones describen los cambios desde la notificación anterior con tres listas de índices: los índices de los objetos que se eliminaron, insertaron y modificaron.
Importante
El orden importa
En los controladores de notificaciones de colecciones, aplique siempre los cambios en el siguiente orden: eliminaciones, inserciones y modificaciones. Gestionar las inserciones antes de las eliminaciones puede provocar un comportamiento inesperado.
Las notificaciones de la colección de resultados proporcionan una estructura results_change que informa el índice de los objetos eliminados, añadidos o modificados. También pueden notificarle si la colección se eliminó.
// Get a results collection to observe auto dogs = realm.objects<realm::Dog>(); // Set up the listener & observe results notifications. auto token = dogs.observe([&](auto&& changes) { try { if (changes.collection_root_was_deleted) { std::cout << "The collection was deleted.\n"; } else { // Handle deletions, then insertions, then modifications. for (auto& resultsChange : changes.deletions) { std::cout << "The object at index " << std::to_string(resultsChange) << " was deleted\n"; } for (auto& resultsChange : changes.insertions) { std::cout << "The object at index " << std::to_string(resultsChange) << " was inserted\n"; } for (auto& resultsChange : changes.modifications) { std::cout << "The object at index " << std::to_string(resultsChange) << " was modified\n"; } } } catch (std::exception const& e) { std::cerr << "Error: " << e.what() << "\n"; } }); // Delete and then add an object to see deletions and insertions. realm.write([&] { realm.remove(firstDog); realm.add(std::move(dog2)); }); // Modify an object to see a modification. realm.write([&] { dog2.age = 2; }); // Refresh the database after the change to trigger the notification. realm.refresh(); // Unregister the token when done observing. token.unregister();
Deja de esperar los cambios
La observación se detiene cuando el token devuelto por una llamada a observe deja de ser válido. Puedes invalidar explícitamente un token llamando a su función miembro unregister().
// Unregister the token when done observing. token.unregister();
Importante
Conserve los tokens durante el tiempo que desee observar
Las notificaciones se detienen cuando se llama al destructor del token. Por ejemplo, si el token está en una variable local que queda fuera de su ámbito. Puedes usar std::move para transferir el token a una variable en un ámbito diferente.
Límites de notificación de cambios
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.