使用 ListView 进行 Flutter 流分页

时间:2021-03-03 11:26:28

标签: firebase flutter dart google-cloud-firestore

在flutter中尝试使用流实现分页时遇到了一些奇怪的行为。 我使用了 bloc 模式来实现这一点,代码如下:


class TransferItemsListBloc {
  DataRepository _db;
  bool showIndicator = false;
  Stream<QuerySnapshot> documentList;
  int incrementSize;
  String searchString;
  DateTime startTime;

 static const int INCREMENT_SIZE = 10;

  BehaviorSubject<QuerySnapshot> transferItemController;

  TransferItemsListBloc() {
    transferItemController = BehaviorSubject<QuerySnapshot>();
    _db = locator<DataRepository>();
    startTime = DateTime.now();
  }


  Stream<QuerySnapshot> get transferItemStream => transferItemController.stream;

  Future<bool> fetchFirstList({String stringToBeSearchedFor}) async {
    incrementSize = INCREMENT_SIZE;

    print('fetchFirstList');

    if (stringToBeSearchedFor != null) {
      this.searchString = stringToBeSearchedFor.toLowerCase();
    } else {
      this.searchString = null;
    }

    documentList = _db.getTransferItemsOrderedByEndTimeInitial(
        incrementSize, startTime, searchString);

    documentList.forEach((element) {
      transferItemController.sink.add(element);
    });

    return true;
  }

重要的部分是搜索字符串。当我将字符串传递给“FetchFirstList”时,我正在过滤结果。如果没有字符串,则不应应用过滤器。

在我展示结果的课程中,我是这样实现的:

    Container(
              child: Expanded(
                child: StreamBuilder<QuerySnapshot>(
                  stream: transferItemsListBloc.transferItemStream,
                  builder: (context, AsyncSnapshot<QuerySnapshot> snapshot) {
                    if (snapshot.connectionState == ConnectionState.waiting) {
                      return Center(child: CircularProgressIndicator());
                    }

                    if (snapshot.hasError) {
                      return Center(child: Text(snapshot.error.toString()));
                    }

                    List<Widget> transferItemsWidgets = [];

                    if (snapshot.hasData) {
                      print('Stream Builder');
                      print('length  of list: ${snapshot.data.docs.length}');

                      print(transferItemsListBloc.searchString);

                      for (QueryDocumentSnapshot qdSnap in snapshot.data.docs) {
                        if (qdSnap.data() != null) {
                          TransferItem item = TransferItem.fromFirebase(qdSnap);

                          if (item != null) {
                            transferItemsWidgets.add(
                                TransferItemInkwellWidget(transferItem: item));
                          }
                        }
                      }
                    }

                    return transferItemsWidgets.length > 0
                        ? ListView.builder(
                            itemCount: transferItemsWidgets.length,
                            controller: scrollController,
                            itemBuilder: (context, index) {
                              return transferItemsWidgets[index];
                            })
                        : Center(child: Text('Keine Angebote verfügbar'));
                  },
                ),
              ),
            ),

如您所见,流被插入到 Streamcontroller 并显示输出。

但是,当流更新时(发生 Firebase 中的更改/更新),流会忽略分页并显示未应用过滤器的结果。因此,每次 Firebase 中发生更新时,我的 ListView 都会切换到原始列表(没有 searchString)。

为什么会这样?

我想它与这里的这部分有关:

documentList = _db.getTransferItemsOrderedByEndTimeInitial(
        incrementSize, startTime, searchString);

    documentList.forEach((element) {
      transferItemController.sink.add(element);
    });

在向接收器添加新元素之前是否必须关闭/排空流?

最好的问候, 马里奥

0 个答案:

没有答案