[英]Flutter pagination with firestore stream
如何在 flutter(在本例中为 flutter web)上使用 firestore stream 正确实施分页? 我目前使用 bloc 的方法很可能是错误的,就像这样
加载下一页时 function 在 bloc 上调用,注意每次调用 function 时,我将 state 的 lastPage 变量增加 1:
Stream<JobPostingState> _loadNextPage() async* {
yield state.copyWith(isLoading: true);
try {
service
.getAllDataByClassPage(state.lastPage+1)
.listen((List<Future<DataJob>> listDataJob) async {
List<DataJob?> listData = [];
await Future.forEach(listDataJob, (dynamic element) async {
DataJob data= await element;
listData.add(data);
});
bool isHasMoreData = state.listJobPostBlock.length!=listData.length;
//Update data on state here
});
} on Exception catch (e, s) {
yield StateFailure(error: e.toString());
}}
调用function获取stream数据
Stream<List<Future<DataJob>>> getAllDataByClassPage(
String className, int page) {
Stream<QuerySnapshot> stream;
if (className.isNotEmpty)
stream = collection
.orderBy('timestamp', "desc")
.where('class', "==", className).limit(page*20)
.onSnapshot;
else
stream = collection.onSnapshot;
return stream.map((QuerySnapshot query) {
return query.docs.map((e) async {
return DataJob.fromMap(e.data());
}).toList();
});
}
使用这种方法,它可以按预期工作,当我加载下一页并仍在收听 stream 时,加载的数据增加了,但我不知道这是否是正确的方法,因为它取代了 stream,它是否可能读取数据两次并最终使我的与不使用分页相比,Firestore 上的读取次数要多得多。 非常感谢任何建议,谢谢。
您的方法确实不是最好的,并且随着您的扩展,您的成本会更高。 我会在你的鞋子里做的是创建一个代表你的流的全局变量,这样你就可以操纵它。 我看不到您的所有代码,因此我将尽可能通用,以便您可以将其应用于您的代码。
首先让我们将流控制器声明为可以保存流值的全局变量:
StreamController<List<DocumentSnapshot>> streamController =
StreamController<List<DocumentSnapshot>>();
之后,我们需要将您的getAllDataByClassPage
函数更改为以下内容:
async getAllDataByClassPage(String className) {
Stream stream = streamController.stream;
//taking out of the code your className logic
...
if(stream.isEmpty){
QuerySnapshot snap = await collection.orderBy('timestamp', "desc")
.where('class', "==", className)
.limit(20)
.onSnapshot
streamController.add(snap.docs);
}else{
DocumentSnapshot lastDoc = stream.last;
QuerySnapshot snap = await collection.orderBy('timestamp', "desc")
.where('class', "==", className)
.startAfterDocument(lastDoc)
.limit(20)
.onSnapshot;
streamController.add(snap.docs);
}
}
之后,您需要做的就是调用streamController.stream;
注意:我没有测试这段代码,但这是您应该尝试做的一般理想。
method.您可以使用方法跟踪最后一个文档以及列表中是否有更多数据。 像这样的
final data = await db
.collection(collection)
.where(field, arrayContains: value)
.limit(limit)
.startAfterDocument(lastDoc)
.get()
.then((snapshots) => {
'lastDoc': snapshots.docs[snapshots.size - 1],
'docs': snapshots.docs.map((e) => e.data()).toList(),
'hasMore': snapshots.docs.length == limit,
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.