我目前正在使用 FirebaseFirestore.instance.collection('cars').get()
从 firebase 获取与汽车详细信息相关的数据。
我将所有 Car 实例保存在 List<Cars> _cars = [];
使用我在 addCarsToList
didChangeDependencies{}
方法
Future<void> addCarsToList({BuildContext context, FilterBy filter}) async {
var lastDocTracker =
Provider.of<LastDocumentTracker>(context, listen: false);
try {
var dcs = filter != null
? await carsCollection.orderBy('dueDate').limit(5).where('readyToRepair', isEqualTo: false).get()
: await carsCollection.orderBy('dueDate').limit(5).get();
//print(dcs.docs.last.data());
for (int i = 0; i < dcs.docs.length; i++) {
Cars carValue = singleCar(dcs, i);
if (_cars.every((item) => item.carId != carValue.carId)) {
_cars.add(carValue);
notifyListeners();
}
}
lastDocTracker.changeLastDocument(dcs.docs.last);
} catch (e) {
print(e);
}
}
这里我使用 lastDocumentTracer 来跟踪最后一个文档以实现分页。
因此,为了实现分页,我使用滚动控制器并调用 getMore
方法
Future<void> getMore(
BuildContext context, QueryDocumentSnapshot lastSnap) async {
print('getMore called');
var lastDocTracker =
Provider.of<LastDocumentTracker>(context, listen: false);
var dcs = await carsCollection
.orderBy('dueDate')
.startAfterDocument(lastSnap)
.limit(5)
.get();
if (dcs.docs.isNotEmpty)
for (int i = 0; i < dcs.docs.length; i++) {
Cars carValue = singleCar(dcs, i);
if (_cars.every((item) => item.carId != carValue.carId)) {
_cars.add(carValue);
notifyListeners();
}
}
if (dcs.docs.isNotEmpty) lastDocTracker.changeLastDocument(dcs.docs.last);
return;
}
我目前面临的问题是我有三个过滤器(全部、即将推出、准备就绪)。
All 表示来自 firebase 的所有汽车,没有任何过滤器。
即将推出是指未来即将推出的汽车。 (在 Firestore 中保存为 DateTime.millisecondsSinceEpoch )
Ready 表示可以修理的汽车(在 firestore 中保存为 bool) Have a look into the screenshot
我正在尝试使用 where((element) => isReadyToRepair)
过滤汽车列表并使用 setState 但不幸的是,因为我将其限制为来自 Firebase 的 5 个项目,如果没有带有字段 isReadyToRepair = true 的汽车,那么我不能向下滚动并使用滚动控制器调用 getMore,因此它显示为空且未加载任何数据。
伙计们,我需要你们的帮助。请帮我。如果我没有解释清楚,请告诉我。
答案 0 :(得分:3)
如果您想同时获得 5 个,您需要对数据库进行 3 次不同的查询并使用 where 方法,您有文档 here。
您的查询将更像这样:
var dcs = await carsCollection
.orderBy('dueDate')
.where('ready', isEqualTo: true)
.startAfterDocument(lastSnap)
.limit(5)
.get();
-- 更新
那是题外话,抱歉了。您需要在 LastDocumentTracker 中创建两个不同的引用。我想您将最后一个文档存储在一个变量中,所以我要做的是为过滤的文档创建一个(或者为您应用的每个过滤器创建一个),并为所有文档创建一个。然后,当您获得文档时,您会根据您应用的过滤器找到正确的变量。为了稍微改进代码维护和优雅,我会使用 addCarsToList 来获得更多和第一次获得它们:
//New addCarsToList
Future<void> addCarsToList(LastDocumentTracker tracker, {FilterBy filter}) async { //Tracker as required and filter as optional
bool hasFilter = filter != null;
var lastSnap = tracker.getLastSnap(filtered: hasFilter);
bool isFirst = lastSnap != null;
var dcs;
try {
if(hasFilter){
dcs = isFirst ? await carsCollection.orderBy('dueDate').limit(5).where('readyToRepair', isEqualTo: false).get() : await carsCollection.orderBy('dueDate').startAfterDocument(lastSnap).limit(5).where('readyToRepair', isEqualTo: false).get()
} else{
dcs = isFirst ? await carsCollection.orderBy('dueDate').limit(5).get(); : await carsCollection.orderBy('dueDate').startAfterDocument(lastSnap).limit(5).get();
}
for (var doc in dcs.docs) {
Cars carValue = singleCar(doc); // Make it get a single document, what's the point on passing both a list and an index ?
if (_cars.every((item) => item.carId != carValue.carId)) { //questionable
_cars.add(carValue);
notifyListeners();
}
}
lastDocTracker.changeLastDocument(dcs.docs.last, filtered: hasFilter);
} catch (e) {
print(e);
}
}
我修改了很多东西,如果你不明白什么,请告诉我。在这之后你应该做一些调整,比如: