繁体   English   中英

Flutter 使用 firestore 分页 stream

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM