您如何组合 2 个 Riverpod StreamProvider,其中 1 个流依赖于另一个流中的数据?

问题描述

有时我认为我理解了提供者的逻辑,然后我在尝试做类似下面的事情时被难住了好几个小时。

我需要从 Firestore 集合流中获取连接 ID 列表。很简单。

但是,我需要将此连接 ID 的流列表提供给另一个 firestore 集合流。下面,您可以看到我即将推出的EventsstreamProvider 是 ref.watch 数据库和connectionsstream。 Riverpod 或 firestore 不会抛出任何错误。但是,在日志中,我按以下顺序看到了我的打印语句:

returned data
returned null stream value

我如何滥用 Riverpod 提供商的权力?哈哈。

final connectionsstreamProvider = StreamProvider<List<UidConnections>>((ref) {
  final database = ref.watch(databaseProvider);
  return database != null ? database.connectionsstream() : Stream.value(null);
});

final connectionsListStateProvider = StateProvider<List>((ref) => []);

final upcomingEventsstreamProvider = StreamProvider<List<SpecialEvents>>((ref) {
  final database = ref.watch(databaseProvider);
  final connectionsstream = ref.watch(connectionsstreamProvider);
  if (database != null && connectionsstream != null) {
    connectionsstream.whenData((data) {
      if (data != null) {
        data.forEach((event) {
          if (event?.active == true && event?.connectedUid != null) {
            ref
                .read(connectionsListStateProvider)
                .state
                .add(event.connectedUid);
          }
        });
        print('returned data');
        return database.upcomingSpecialEventsstream(
            ref.read(connectionsListStateProvider).state);
      }
    });
  }

  print('returned null stream value');
  return Stream.value(null);
});

或者,我是否只需要重构我的 Firebase Cloud Firestore 查询来首先获取连接 ID 流?我宁愿使用 Riverpod,因为我仍然需要单独的连接 ID 流。

解决方法

仍然对如何将 2 个流与 Riverpod 单独结合感到困惑。但是,我确实设法解决了我的问题,这里是其他任何遇到此用例的人的信息,其中一个流依赖于另一个流中的数据。

行之有效的解决方案是使用 rxdart Rx.combineLatest2。见下文。现在 Riverpod 很高兴,并为我的合并流提供状态。由于 rxdart,我需要的连接 ID 现在是我帐户模型的一部分。希望这对那里的人有所帮助。

final accountInfoStreamProvider = StreamProvider<Account>((ref) {
  final database = ref.watch(databaseProvider);
  return database != null
      ? AccountInfoModel(database: database).accountInfoStream()
      : Stream.value(null);
});

class AccountInfoModel {
  AccountInfoModel({@required this.database});
  final FirestoreDatabase database;

  Stream<Account> accountInfoStream() {
    return Rx.combineLatest2(
      database.accountStream(),database.connectionsStream(),(Account account,List<Connections> connections) {
        connections.forEach((connection) {
          account.connections.add(connection.documentId);
        });
        return account;
      },);
  }
}