【问题标题】:Riverpod's StreamProvider yields StreamValue only once | Flutter & HiveRiverpod 的 StreamProvider 只产生一次 StreamValue |颤振和蜂巢
【发布时间】:2021-04-16 14:32:09
【问题描述】:

我编写了一个 StreamProvider,我在启动后立即收听它以获取有关可能登录用户的所有信息。如果没有用户,那么结果将为空,监听器保持在加载状态,所以我决定发回一个空用户的默认值,让我知道加载完成。 我必须这样做,因为 Hive 的 watch() 方法仅在数据更改时触发,而在启动时不会触发。 所以在那之后,我希望 watch() 方法完成它的工作,但问题在于以下场景:

  1. 启动时:无用户 - 插入用户 -> 触发 watch 方法 -> 我得到插入的用户数据 -> 删除登录用户 -> 不触发 watch 方法。

  2. 启动时:完整用户 - 删除用户 -> 触发 watch 方法 -> 我得到一个空用户 -> 插入用户 -> 不触发 watch 方法。

一段时间后,我发现我可以随心所欲地使用所有 CRUD 操作,并且 Hive 的盒子做了它应该做的事情,但是 watch() 方法在它被触发后不再被触发 一次

流提供者:

final localUsersBoxFutureProvider = FutureProvider<Box>((ref) async {
  final usersBox = await Hive.openBox('users');
  return usersBox;
});

final localUserStreamProvider = StreamProvider<User>((ref) async* {
  final usersBox = await ref.watch(localUsersBoxFutureProvider.future);

  yield* Stream.value(usersBox.get(0, defaultValue: User()));
  yield* usersBox.watch(key: 0).map((usersBoxEvent) {
    return usersBoxEvent.value == null ? User() : usersBoxEvent.value as User;
  });
});

聆听者:

return localUserStream.when(
  data: (data) {
    if (data.name == null) {
      print('Emitted data is an empty user');
    } else {
      print('Emitted data is a full user');
    }

    return Container(color: Colors.blue, child: Center(child: Row(children: [
      RawMaterialButton(
        onPressed: () async {
          final globalResponse = await globalDatabaseService.signup({
            'email' : 'name@email.com',
            'password' : 'password',
            'name' : 'My Name'
          });

          Map<String, dynamic> jsonString = jsonDecode(globalResponse.bodyString);
          await localDatabaseService.insertUser(User.fromJSON(jsonString));
        },
        child: Text('Insert'),
      ),
      RawMaterialButton(
        onPressed: () async {
          await localDatabaseService.removeUser();
        },
        child: Text('Delete'),
      )
    ])));
  },
  loading: () {
    return Container(color: Colors.yellow);
  },
  error: (e, s) {
    return Container(color: Colors.red);
  }
);

CRUD 方法:

Future<void> insertUser(User user) async {
    Box usersBox = await Hive.openBox('users');
    await usersBox.put(0, user);
    await usersBox.close();
  }

  Future<User> readUser() async {
    Box usersBox = await Hive.openBox('users');
    User user = usersBox.get(0) as User;
    await usersBox.close();
    return user;
  }

  Future<void> removeUser() async {
    Box usersBox = await Hive.openBox('users');
    await usersBox.delete(0);
    await usersBox.close();
  }

知道如何告诉 StreamProvider watch() 方法应该保持活动状态,即使已经发出了一个值?

【问题讨论】:

  • 您能告诉我您的localDatabaseService 实现是什么吗?我尝试用Riverpod 实现Hive 的缩写
  • 我实现的每个方法都可以在“CRUD 方法”下的问题中找到。
  • 我再次阅读,localDatabaseServicelocalUserStream 实现在您的帖子中不存在
  • @DolDurma 我真的不明白你在寻找什么。 “localDatabaseService”是用于“LocalDatabaseService”类实例的变量,您应该能够在我的问题中看到其 CRUD 操作。 “localUserStream”也是我从 localUserStreamProvider 获得的变量。

标签: flutter dart riverpod flutter-hive


【解决方案1】:

但是 watch() 方法被触发后不再触发 一次

那是因为在每次 CRUD 之后您都关闭了盒子,所以流(使用该盒子)停止发出值。如果您从 Riverpod (await Hive.openBox('users')) 以外的某个地方调用它,它调用相同的引用并不重要。您应该仅在停止使用它时关闭该框,我建议您在不再使用时使用 autodispose 和 Riverpod 来关闭它,并且可能将这些 CRUD 方法放在由 Riverpod 控制的类中,这样您就可以完全控制它的生命周期盒子

final localUsersBoxFutureProvider = FutureProvider.autoDispose<Box>((ref) async {
  final usersBox = await Hive.openBox('users');

  ref.onDispose(() async => await usersBox?.close()); //this will close the box automatically when the provider is no longer used
  return usersBox;
});

final localUserStreamProvider = StreamProvider.autoDispose<User>((ref) async* {
  final usersBox = await ref.watch(localUsersBoxFutureProvider.future);

  yield* Stream.value(usersBox.get(0, defaultValue: User()) as User);
  yield* usersBox.watch(key: 0).map((usersBoxEvent) {
    return usersBoxEvent.value == null ? User() : usersBoxEvent.value as User;
  });
});

并且在您的方法中使用来自 localUsersBoxFutureProvider 的相同实例框,并且不要在每个实例之后关闭该框,当您停止收听 streamlocalUsersBoxFutureProvider 时,它会自行关闭

【讨论】:

  • 我会把你的名字写进我的祈祷中!
猜你喜欢
  • 2021-01-29
  • 2021-04-09
  • 2021-10-07
  • 2019-12-08
  • 1970-01-01
  • 2021-07-12
  • 2021-12-12
  • 2022-12-04
  • 1970-01-01
相关资源
最近更新 更多