FutureBuilder无数据返回,如何高效获取Firestore文档计数?
Firestore计数查询在FutureBuilder中无响应的问题及优化方案
问题描述
在使用FutureBuilder获取Firestore中广告浏览事件集合的文档数量时,以下方法既不返回数据也不抛出错误,加载指示器持续转动:
最初的计数方法代码
/// Stores and returns the document [id]. static Future<int> getCount({required String? adId}) { if (adId == null) return Future<int>.value(0); // = Actually store the document final c = FirebaseFirestore.instance .collection(collectionName) .where("adId", isEqualTo: adId) .snapshots() .length; return c; }
对应的FutureBuilder代码
FutureBuilder( future: ClassifiedAdSeen.getCount(adId: ad.id), builder: (context, snapshot) { if (snapshot.hasError) { return const Icon(Icons.error); } else if (!snapshot.hasData) { return const CircularProgressIndicator(); } final count = snapshot.data ?? "—"; return Text("$count"); }),
更新说明
改用get()方法获取整个查询快照后可以正常得到计数,但这种方式需要拉取所有匹配的文档数据,会浪费内存和带宽。请问仅获取文档计数的最佳方式是什么?
更新后的代码
/// Stores and returns the document [id]. static Future<int> getCount({required String? adId}) async { if (adId == null) return 0; // = Actually store the document final c = await FirebaseFirestore.instance .collection(collectionName) .where("adId", isEqualTo: adId) .get(); return c.size; }
问题原因
最初代码里用了snapshots()方法,这个方法返回的是Streamlength属性是错误的操作。Stream的length是一个Future<int>,但它统计的是流中已发出的事件数量,而非Firestore集合里的文档总数——而且这个流会持续监听集合变化,永远不会进入完成状态,导致FutureBuilder一直处于等待状态,加载指示器停不下来。
优化方案:高效获取Firestore文档计数
如果不想拉取所有文档数据,推荐使用Firestore的计数查询(count()),它只返回匹配的文档数量,不会传输文档内容,能大幅节省带宽和内存:
static Future<int> getCount({required String? adId}) async { if (adId == null) return 0; final countSnapshot = await FirebaseFirestore.instance .collection(collectionName) .where("adId", isEqualTo: adId) .count() .get(); return countSnapshot.count; }
注意事项
- 确保你的Firebase SDK版本支持
count()方法(Firebase Firestore Dart SDK 4.0.0及以上版本支持) - 计数查询的配额消耗远低于读取所有文档:1个计数查询最多消耗1个读取配额,不受匹配文档数量影响
内容的提问来源于stack exchange,提问作者Stéphane de Luca
相关产品推荐
相关产品推荐

