React 变更 - C++ SDK
所有 Realm 对象均为活动对象,这表示在修改它们时会自动进行更新。每当发生任何属性变更时,Realm 均会发出通知事件。您可以注册一个通知处理程序来侦听这些通知事件,并使用最新数据更新您的用户界面。
注册对象变更侦听器
您可以在 Realm 中的特定对象上注册通知处理程序。Realm 会通知您的处理程序:
当删除对象时。
当对象的任何属性发生变更时。
auto token = object.observe([&](auto&& change) { ... }
处理程序接收一个 object_change对象,其中包含有关更改的信息,例如对象是否已删除。 它可能包括一个PropertyChange对象列表,其中包含有关更改的字段、这些字段的新值(列表属性除外)以及可能的字段的旧值的信息。
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"; } }
进行更改时,对 Realm 进行刷新以发出通知。
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();
注册集合变更监听器
您可以在collection上注册通知处理程序。集合是列表、映射或集属性,可以包含任何受支持的数据类型,包括基元或其他对象。
每当写事务(write transaction)删除、添加或更改collection中的对象时,Realm 都会通知您的处理程序。
通知使用三个索引列表描述自先前通知以来的更改:已删除对象的索引、已插入对象的索引和已修改对象的索引。
重要
顺序很重要
在集合通知处理程序中,始终按以下顺序应用变更:删除、插入和修改。在删除操作之前处理插入操作可能会导致意外行为。
集合通知提供了一个collection_change结构体,用于报告已删除、添加或修改的对象的索引。 如果集合已删除,它还可以通知您。
在此示例中, Person
对象将Dog
对象列表作为属性:
struct Person { std::string name; std::vector<Dog*> dogs; }; REALM_SCHEMA(Person, name, dogs)
删除犬、添加新犬或修改犬会触发通知处理程序:
// 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();
注册结果collection变更监听器
您可以在结果集合上注册通知处理程序。
每当写事务(write transaction)删除、添加或更改collection中的对象时,Realm 都会通知您的处理程序。
通知使用三个索引列表描述自先前通知以来的变更:已删除对象、已插入对象和已修改对象的索引。
重要
顺序很重要
在集合通知处理程序中,始终按以下顺序应用变更:删除、插入和修改。在删除操作之前处理插入操作可能会导致意外行为。
结果集合通知提供了一个results_change结构体,用于报告已删除、添加或修改的对象的索引。 如果集合已删除,它还可以通知您。
// 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();
停止关注变更
当observe
调用返回的令牌失效时,观察就会停止。 您可以通过调用令牌的unregister()
成员函数来显式使其失效。
// Unregister the token when done observing. token.unregister();
重要
只要您想观察,就保留令牌
调用令牌的析构函数时,通知停止。 例如,如果令牌位于Go作用域的局部变量中。您可以使用std::move
将令牌传输到不同作用域中的变量。
变更通知限制
嵌套文档中深度超过四级的变更不会触发变更通知。
如果您的数据结构需要侦听第五层深度或更深层的更改,解决方法包括:
重构模式以减少嵌套。
添加“推送以刷新”一类的内容,使用户能够手动刷新数据。