如何在firebase firestore中准确合并多个流
Posted
技术标签:
【中文标题】如何在firebase firestore中准确合并多个流【英文标题】:How exactly to merge multiple streams in firebase firestore 【发布时间】:2020-12-09 13:51:04 【问题描述】:在你说这是一个重复的问题或者我应该使用嵌套流构建器之前,请听我说完。
我正在设计一个社交媒体类型的应用程序。我希望用户在他们关注的人在他们的“我的关注者帖子”集合中发布内容时收到更新。 在应用程序中,应用程序将检查当前用户的关注列表(他关注的人)的 firebase rtdb 并列出他们的 uid。
我计划使用所述列表创建一个流列表(当然是按时间排序)并将它们合并到一个流中,然后将其馈送到私人提要页面上的流构建器中。
在此页面上,用户将能够轻松地关注他们感兴趣的人发布的内容。
我认为这样的系统比在“私人 Feed”集合中拥有文档的每个用户更具成本效益,每当有人发布内容时,该应用程序都会读取他们的关注者列表,然后及时在每个用户中发布更新他们的私人供稿之一。 因为... 想象一下拥有 200 万粉丝的人。即刻有 200 万次写入。后来,200 万次阅读。 我认为发帖者只需将帖子放在他们的“publicFeed”中,而不同的追随者只需收听该提要并与他们保持密切联系,就会更具成本效益。
但是.. 这需要实现多个流的合并(超过 2 个)。我该怎么做?
我尝试过阅读 RxDart,但对我来说它完全是希腊语。我是飞镖的初学者。我现在只写了大约 5 个月的代码。
【问题讨论】:
【参考方案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> 而不是 StreamCombineLatestStream.list
它使用了一个对 StreamCombineLatestStream(streamList, combinerFunc)
。以上是关于如何在firebase firestore中准确合并多个流的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Firebase Firestore 获取子集合? [复制]
如何遍历 Firestore(React 和 Firebase Web 应用程序)中的多个用户子集合?