观察者(Watcher)
Isar 允许你订阅数据库中的变化。你可以“观察”单个对象、整个 Collection 或单个查询的变化。
观察者可以让你针对数据库中的变化高效地做出回应。例如,当一个联系人被添加之后,你可以重建 UI;或当一个文件被修改后,发送一个网络请求等等。
当事务成功被执行后,目标被修改,然后就会通知观察者。
观察对象
如果你想在某个对象被创建、修改或删除时收到通知,你可以通过下面代码观察该对象:
Stream<User> userChanged = isar.users.watchObject(5);
userChanged.listen((newUser) {
print('User changed: ${newUser?.name}');
});
final user = User(id: 5)..name = 'David';
await isar.users.put(user);
// 打印出:User changed: David
final user2 = User(id: 5)..name = 'Mark';
await isar.users.put(user);
// 打印出:User changed: Mark
await isar.users.delete(5);
// 打印出:User changed: null
如你所见,声明观察者的时候,Id 为 5 的对象还未被创建。一旦被创建,观察者就会收到通知。
还有一个参数 fireImmediately
,如果你设置为 true
,Isar 会立刻将该对象的当前值添加到 Stream 中。
懒观察
也许你不需要知道一个对象的最新值,只需了解其是否被修改过,那么可以用懒观察,这样 Isar 无需去读取该对象的值:
Stream<void> userChanged = isar.users.watchObjectLazy(5);
userChanged.listen(() {
print('User 5 changed');
});
final user = User(id: 5)..name = 'David';
await isar.users.put(user);
// 打印出:User 5 changed
观察 Collection
除了观察单个对象,你也可以观察整个 Collection 中是否有对象被添加、修改或删除:
Stream<void> userChanged = isar.users.watchLazy();
userChanged.listen(() {
print('A User changed');
});
final user = User()..name = 'David';
await isar.users.put(user);
// 打印出: A User changed
观察查询
甚至你也可以观察整个查询的结果是否发生变化。Isar 尽力只在查询结果真正发生变化时通知你。但是当由关联造成查询结果发生变化时,你不会收到任何通知。针对关联变化,你可以观察 Collection。
Query<User> usersWithA = isar.users.filter()
.nameStartsWith('A')
.build();
Stream<List<User>> queryChanged = usersWithA.watch(fireImmediately: true);
queryChanged.listen((users) {
print('Users with A are: $users');
});
// 打印出:Users with A are: []
await isar.users.put(User()..name = 'Albert');
// 打印出:Users with A are: [User(name: Albert)]
await isar.users.put(User()..name = 'Monika');
// 无任何打印输出
await isar.users.put(User()..name = 'Antonia');
// 打印出:Users with A are: [User(name: Albert), User(name: Antonia)]
警告
如果你的查询使用了偏移量和限制,或者进行了去重化,即使是在查询结果范围之外的对象,若符合该查询条件,Isar 也会通知你查询结果发生了变化。
就像观察对象的懒观察一样,你也可以使用 watchLazy()
来懒观察一条查询结果是否有变化,而无需去读取查询的结果。
危险
观察查询时返回每一个变动是十分低效的。尽量使用懒观察 Collection 来代替。