【问题标题】:How exactly to merge multiple streams in firebase firestore如何在firebase firestore中准确合并多个流
【发布时间】:2020-12-09 13:51:04
【问题描述】:

在你说这是一个重复的问题或者我应该使用嵌套流构建器之前,请听我说完。

我正在设计一个社交媒体类型的应用程序。我希望用户在他们关注的人在他们的“我的关注者帖子”集合中发布内容时收到更新。 在应用程序中,应用程序将检查当前用户的关注列表(他关注的人)的 firebase rtdb 并列出他们的 uid。

我计划使用所述列表创建一个流列表(当然是按时间排序)并将它们合并到一个流中,然后将其馈送到私人提要页面上的流构建器中。

在此页面上,用户将能够轻松地关注他们感兴趣的人发布的内容。

我认为这样的系统比在“私人 Feed”集合中拥有文档的每个用户更具成本效益,每当有人发布内容时,该应用程序都会读取他们的关注者列表,然后及时在每个用户中发布更新他们的私人供稿之一。 因为... 想象一下拥有 200 万粉丝的人。即刻有 200 万次写入。后来,200 万次阅读。 我认为发帖者只需将帖子放在他们的“publicFeed”中,而不同的追随者只需收听该提要并与他们保持密切联系,就会更具成本效益。

但是.. 这需要实现多个流的合并(超过 2 个)。我该怎么做?

我尝试过阅读 RxDart,但对我来说它完全是希腊语。我是飞镖的初学者。我现在只写了大约 5 个月的代码。

【问题讨论】:

    标签: firebase flutter merge stream stream-builder


    【解决方案1】:

    您可以使用 async 包中的 StreamGroup:https://pub.dev/documentation/async/latest/async/StreamGroup-class.html 对来自多个流的事件进行分组 - 它由 dart 团队进行了详细记录和维护。如果您没有 RxDart 经验,这是一个不错的选择。它没有 rx 的所有功能,但对于初学者来说应该更容易理解它

    【讨论】:

    • 你能给我一个简单的例子来说明如何做到这一点。我完全是通过 youtube 教程学习的,所以,我还不擅长解码文档的编写方式。我从例子中学习得更好。假设您在新的 Cars 集合中有数据,在 newClothesCollection 中有一些其他数据,在 newKeyBoards 集合中有一些其他数据。您能否编写一些演示代码,说明如何使用 async 合并这三个并将它们提供给流构建器?
    • 我已经设法使用它合并流,它确实有效。但是,关于在流构建器中显示合并的流,我面临一个全新的、完全不同的问题。不过,我将把它作为一个新问题发布。谢谢。
    【解决方案2】:

    我最近有一个类似的案例,我建议你做的是这个 (我正在使用 Cloud Firestore,但我确定您已经编写了流,所以重要的部分是多个流的使用):

    您必须将此插件添加到 pub spec.yaml: https://pub.dev/packages/rxdart

    这里是(在您的帖子中,比如说 newPosts、oldPosts)的存储库:

    class PostRepository {
    
      static CollectionReference get collection => yourCollectionRef;
        
      static Stream<List<Post>> newPosts() {
        Query query = collection
            .where('Your condition like was viewed', isEqualTo: false)
            .orderBy('updateDate', descending: true)
            .limit(50);
        return query.snapshots().map<List<Post>>((querySnapshot) {
          final _newPosts = querySnapshot.documents.map((doc) {
            final post = Post.fromDoc(doc);
            return post;
          }).where((p) => p != null);
    
          return _newPosts
        });
      }
    
      static Stream<List<Post>> oldPosts() {
        Query query = collection
            .where('Your condition like was viewed', isEqualTo: true)
            .orderBy('updateDate', descending: true)
            .limit(50);
        return query.snapshots().map<List<Post>>((querySnapshot) {
          final _oldPosts = querySnapshot.documents.map((doc) {
            final post = Post.fromDoc(doc);
            return post;
          }).where((p) => p != null);
    
          return _oldPosts
        });
      }
    }
    

    然后要获得多个流(上面的两个流结合在一起),请在您的小部件类中执行以下操作:

    重要!你必须导入这个 - import 'package:rxdart/streams.dart';

    List<Post> newPosts;
    List<Post> oldPosts;
    
    Widget _pageContent() {
      return SingleChildScrollView(
        child: Column(
          children: [
            ListView.builder(
              shrinkWrap: true,
              physics: NeverScrollableScrollPhysics(),
              itemCount: newPosts.length,
              itemBuilder: (context, index) {
                return ListTile(
                  title: Text(newPosts[index].title)
                );
              }
            ),
            ListView.builder(
              shrinkWrap: true,
              physics: NeverScrollableScrollPhysics(),
              itemCount: oldPosts.length,
              itemBuilder: (context, index) {
                return ListTile(
                  title: Text(oldPosts[index].title)
                );
              }
            )
          ]
        )
      );
    }
    
    Widget _posts() {
      return StreamBuilder(
        stream: CombineLatestStream.list([
          PostRepository.getNewPosts(),
          PostRepository.getOldPosts()
        ]),
        builder: (context, snap) {
         if (snap.hasError) {
    
            debugPrint('${snap.error}');
            return ErrorContent(snap.error);
    
          } else if (!snap.hasData) {
    
            return Center(
              child: CircularProgressIndicator(),
            );
    
          }
    
          newPosts = snap.data[0];
          oldPosts = snap.data[1];
    
          return _pageContent();
        }
      );
    }
    

    我的代码是从头开始写的,所以可能会有一些小错误,但我希望你明白这一点,享受:)

    【讨论】:

    • 非常感谢。虽然我认为不可能将列表视图放在滚动视图中。我以前做过,它给出了一些错误,比如“你不能把一个可滚动的东西放在另一个可滚动的虚拟对象中”。不过,我将尝试您的解决方案,然后给您反馈。
    • 好的。如果您像示例中那样使用 shrinkwrap 和 neverscrollablescrollphysics,那么您的 2 个列表应该完全符合您的要求:)
    • 非常感谢。我设法使用流组合并流,但我目前面临在流构建器中显示此合并流的新问题。但我将它作为一个全新的问题发布。谢谢你。
    • 请注意,如果您想合并集合流(Stream> 而不是 Stream,您需要使用自定义合并器函数 - 在此示例中,他调用 CombineLatestStream.list它使用了一个对 Stream 有好处的默认组合器。在我的情况下,我无法让它工作,直到我意识到使用 Stream> 时你需要提供一个自定义组合器来处理它(获取一个 List> 然后根据需要将其展平以获得一个 Stream>)。所以你需要使用常规的CombineLatestStream(streamList, combinerFunc)
    猜你喜欢
    • 1970-01-01
    • 2021-07-16
    • 2019-04-02
    • 1970-01-01
    • 2021-06-05
    • 2019-04-16
    • 1970-01-01
    • 2023-03-26
    • 2015-11-29
    相关资源
    最近更新 更多