【问题标题】:How to combine Riverpod StreamProvider in Flutter?如何在 Flutter 中结合 Riverpod StreamProvider?
【发布时间】:2021-10-20 15:36:40
【问题描述】:

我一直在尝试合并两个 Riverpod StreamProvider。 目标是根据来自 Firestore 的其他数据对 Firestore 执行查询以获取数据,如下所示:

  1. 从 Firestore 文档中获取用户数据
  2. 使用该数据执行另一个查询

这是我共享 FirestoreDatabase 类实例的数据库提供程序:

final databaseProvider = Provider<FirestoreDatabase>((ref) {
  final auth = ref.watch(authStateChangesProvider);

  if (auth.data?.value?.uid != null) {
    return FirestoreDatabase(uid: auth.data!.value!.uid);
  }
  throw UnimplementedError();
});

然后我创建了一个 StreamProvider 来获取用户的数据

final userProvider = StreamProvider<UserModel>((ref) {
  final database = ref.watch(databaseProvider);
  return database.getUser();
});

现在我需要创建最后一个提供程序,但我无法使其工作。 这是我从现在开始写的:

final nodesProvider = StreamProvider<List<Node>>((ref) {
  final database = ref.watch(databaseProvider);
  final user = ref.watch(userProvider);

  //... some code to await user data fetching

  // user.nodes contains the list I need to pass in order to perform the query
  return database.getNodes(user.nodes);
});

有人可以帮助我或给我一个提示吗? 提前致谢

【问题讨论】:

    标签: flutter google-cloud-firestore riverpod


    【解决方案1】:

    根据个人经验,我建议远离 StreamProviders,除非它只有一层深度(没有依赖于其他流的流)。

    相反,Riverpod 有一个 .last 提供程序,它公开流中的最后一个值。致电ref.watch 将让您收听它和任何更新。

    final databaseProvider = FutureProvider<FirestoreDatabase>((ref) async {
      final auth = await ref.watch(authStateChangesProvider.last);
    
      if (auth.data?.value?.uid != null) {
        return FirestoreDatabase(uid: auth.data!.value!.uid);
      }
      throw StateError('auth uid is null so no database could be created');
    });
    
    final nodesProvider = FutureProvider<List<Node>>((ref) async {
      // you can Future.wait these if you want
      final database = await ref.watch(databaseProvider);
      final user = await ref.watch(userProvider.last);
    
      return database.getNodes(user.nodes);
    });
    

    我认为这会起作用,尽管我的语法可能有点错误(在 SO 文本区域中写下这个)。另一方面,有一些方法可以在流中收听流,但我从来没有运气。这就是我认为的样子。

    final databaseProvider = StreamProvider<FirestoreDatabase?>((ref) async* {
      // Or any loading value really... Idk if I'd actually do this
      yield null;
    
      for await (final authState in ref.watch(authStateChangesProvider.stream)) {
        if (auth.data?.value?.uid != null) {
          yield FirestoreDatabase(uid: auth.data!.value!.uid);
        }
      }
    });
    
    final nodesProvider = StreamProvider<List<Node>?>((ref) async* {
      // [Edit] You could probably use combineStream from rxDart here
      for await (final database in await ref.watch(databaseProvider.stream)) {
        if (database != null) {
          for await (final user in ref.watch(userProvider.stream)) {
            yield database.getNodes(user.nodes);
          }
        }
      }
    });
    

    【讨论】:

      猜你喜欢
      • 2021-03-19
      • 1970-01-01
      • 2021-08-02
      • 2022-11-28
      • 2021-10-03
      • 1970-01-01
      • 2020-11-04
      • 2022-12-04
      • 2021-11-16
      相关资源
      最近更新 更多