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

Posted

技术标签:

【中文标题】如何组合 2 个 Riverpod StreamProviders,其中 1 个流依赖于另一个流的数据?【英文标题】:How do you combine 2 Riverpod StreamProviders where 1 stream depends on the data from another stream? 【发布时间】:2021-06-15 02:09:33 【问题描述】:

有时我认为我得到了提供者的逻辑,然后我被难住了好几个小时试图做下面这样的事情。

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

但是,我需要将此连接 ID 的流式传输列表提供给另一个 Firestore 集合流。下面,您可以看到我的即将到来的EventsStreamProvider 是 ref.watch 数据库和连接流。 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 流。

【问题讨论】:

我不确定这是否能解决你的整个问题,但你应该添加一个 return: return connectionsStream.whenData... 因为你正在返回你的 database.upcomingSpecialEventsStream 但不是从 whenData 返回它。跨度> 不幸的是,尝试过,但它只会返回 AsyncValue。 对,但这应该是一个 AsyncValue ,您可以使用 AsyncValue.when(data, loading, err) 读取它 添加return时返回类型为AsyncValue 我看到@double-beep。已发布答案。 【参考方案1】:

仍然难以解决如何单独使用 Riverpod 完成 2 个流的组合。但是,我确实设法解决了我的问题,这里是遇到此用例的其他任何人的信息,其中流依赖于来自另一个流的数据。

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

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;
      ,
    );
  

【讨论】:

以上是关于如何组合 2 个 Riverpod StreamProviders,其中 1 个流依赖于另一个流的数据?的主要内容,如果未能解决你的问题,请参考以下文章

Flutter状态管理之Riverpod

Riverpod - 如何在消费者中包装 PreferredSizeWidget

如何在 Riverpod 中显示来自 StateNotifier 的小吃店?

Flutter Riverpod:如何实现 FutureProvider?

如何覆盖 Riverpod StateNotifier 的状态以进行测试

如何在不传递参数的情况下使用riverpod 系列提供程序