在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);
});
在向接收器添加新元素之前是否必须关闭/排空流?
最好的问候, 马里奥