Google cloud firestore 实现firestore无限查询列表,该列表在集合更改时更新
我想说什么? 我目前在firestore后端实现实时更新的无限滚动列表时遇到了一系列问题 在我的应用程序中,我希望向用户显示评论(如YouTube或其他社交媒体网站)。由于集合中的注释数量可能相当大,我看到了一个选项,可以对集合进行分页,同时接收基于快照的实时更新。因此,我最初加载Google cloud firestore 实现firestore无限查询列表,该列表在集合更改时更新,google-cloud-firestore,bloc,Google Cloud Firestore,Bloc,我想说什么? 我目前在firestore后端实现实时更新的无限滚动列表时遇到了一系列问题 在我的应用程序中,我希望向用户显示评论(如YouTube或其他社交媒体网站)。由于集合中的注释数量可能相当大,我看到了一个选项,可以对集合进行分页,同时接收基于快照的实时更新。因此,我最初加载x注释时,只要用户按下按钮,就可以加载最多x更多项目。在下图中x=3 标准溶液 基于其他SO问题,我发现应该使用.limit()和.startAfter()方法来实现这种行为。 因此,第一页加载为: query =
x
注释时,只要用户按下按钮,就可以加载最多x
更多项目。在下图中x=3
标准溶液
基于其他SO问题,我发现应该使用.limit()
和.startAfter()
方法来实现这种行为。
因此,第一页加载为:
query = this
.collection
.orderBy('date', descending: true)
.limit(pageSize);
query.snapshots().map((QuerySnapshot snap) {
lastVisible = snap.documents.last;
// convert the DocumentSnapshot into model object
});
所有其他页面均加载以下代码:
query = this.collection
.orderBy('date', descending: true)
.startAfterDocument(lastVisible)
.limit(pageSize);
此外,我想补充一点,这段代码位于一个repository类中,该类与BLoC模式一起使用,类似于中所示的代码。
虽然Felix使用一个简单的颤振列表来显示项目,但我有一个页面列表,其中显示了基于其集团提供的数据的评论。请注意,每个BLoC访问一个共享存储库(存储库代码的一部分如下所示)
标准解决方案的问题
通过上面显示的代码,我看到了多个问题:
.limit()
运算符,已存在的另一条注释不再显示。可以将限制增加一个,但我不确定如何编辑快照查询。在无法编辑快照查询的情况下,可以创建一个新的(更大的)查询,但这将需要额外的读取
x
项。然后创建一个查询,该查询使用.startAtDocument()
和.endAtDocument()
以一定的间隔获取所需的项目,从而消除了.limit()
操作符
DocumentSnapshot pageStartDocument;
DocumentSnapshot pageEndDocument;
Future<Stream<List<Comment>>> comments() async {
// This fetches the first and next Document as initialization
// (maybe should be implemented in constructor)
if (pageStartDocument == null) {
Query query = collection
.orderBy('date', descending: true)
.limit(pageSize);
QuerySnapshot snap = await query.getDocuments();
pageStartDocument = snap.documents.first;
pageEndDocument = snap.documents.last;
} else {
Query query = collection
.orderBy('date', descending: true)
.startAfterDocument(pageEndDocument)
.limit(pageSize);
QuerySnapshot snap = await query.getDocuments();
pageStartDocument = snap.documents.first;
pageEndDocument = snap.documents.last;
}
// This fetches a subcollection of elements from the collection
// with the tradeof of double the reads
Query query = this
.collection
.orderBy('date', descending: true)
.startAtDocument(pageStartDocument)
.endAtDocument(pageEndDocument);
return query.snapshots().asyncMap((QuerySnapshot snap) async {
// convert the QuerySnapshot into model objects
});
文档快照页面开始文档;
文档快照页面结束文档;
Future comments()异步{
//这将获取第一个和下一个文档作为初始化
//(可能应该在构造函数中实现)
如果(pageStartDocument==null){
查询=集合
.orderBy('date',降序:true)
.限制(页面大小);
QuerySnapshot snap=wait query.getDocuments();
pageStartDocument=snap.documents.first;
pageEndDocument=snap.documents.last;
}否则{
查询=集合
.orderBy('date',降序:true)
.startAfterDocument(pageEndDocument)
.限制(页面大小);
QuerySnapshot snap=wait query.getDocuments();
pageStartDocument=snap.documents.first;
pageEndDocument=snap.documents.last;
}
//这将从集合中获取元素的子集合
//以加倍的阅读量为代价
Query=this
收集
.orderBy('date',降序:true)
.StartDocument(pageStartDocument)
.endAtDocument(pageEndDocument);
返回query.snapshots().asyncMap((QuerySnapshot snap)async{
//将QuerySnapshot转换为模型对象
});
如代码中所述,此解决方案有以下缺点:
pageStartDocument
和pageEndDocument
需要一个查询,因此读取的次数增加了一倍,因为在创建第二个查询时会再次读取所有数据。由于我相信数据是兑现的,所以性能影响可能可以忽略,但是,具有2倍的数据库读取成本可能会非常大李>
问题:
由于我不仅实现分页,而且还实现实时更新(使用集合插入),因此.limit()
操作符在我的情况下似乎不起作用
如何实现带有实时更新的分页(没有双重读取)
旁注:
我看了怎么做,但在视频中它似乎并不是那么琐碎(有人提出,可能需要权衡)
如果需要我方的进一步代码,请在评论中说明
对于注释场景,将项目插入到(排序的)注释的中间是没有意义的收集。但是,如果场景需要这样的功能,我想了解应该如何实现它。这可能是一个很晚的答案。OP可能不再需要帮助,但是对于任何偶然发现这一点的人,我编写了一个教程,其中包含一个部分解决此问题的解决方案:
- Bloc保留流订阅列表,以跟踪列表的实时更新
- 然而,关于插入问题,因为当您将有基于文档光标的分页流时,在插入或删除时,您必须重置分页流订阅,除非它是最后一页。 因此,我的解决方案是在发生修改时更新列表,但在发生修改时重置列表