如何在Firebase Firestore中准确合并多个流

问题描述

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

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

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

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

我认为,与每个在“私人Feed”集合中拥有文档的用户相比,这样的系统更具成本效益,每当有人发布内容时,该应用都会读取其关注者列表,然后迅速在每个人中发布更新他们的私人供稿之一。 因为...想像一个拥有200万关注者的人。即刻写入200万。后来读取了200万次。 我认为将海报发布到他们的“ publicFeed”中,使发布者更具成本效益,而不同的关注者只需听取该Feed并与他们保持联系即可。

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

我曾尝试阅读RxDart,但对我来说这是希腊文。我是飞镖的初学者。我现在才编码大约5个月。

解决方法

我最近有一个类似的案例,我建议您这样做 (我使用的是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
    });
  }
}

然后获取多个流(上面的两个流合并),在小部件类中这样做:

重要!您必须导入此文件-导入'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,itemCount: oldPosts.length,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();
    }
  );
}

我从头开始就编写了代码,因此可能会有一些小错误,但我希望您明白了,喜欢:)

,

您可以使用异步包https://pub.dev/documentation/async/latest/async/StreamGroup-class.html中的StreamGroup对来自多个流的事件进行分组-飞镖团队对此文件进行了很好的记录和维护。如果您没有RxDart经验,这是一个不错的选择。它不具有rx的所有功能,但对于初学者来说,应该更容易将其包裹住