Flutter如何在分类卡片显示ListView对应分类的条目总数
问题根因
- 分类页
build方法内初始化的cases列表是空数组,从未从Firestore拉取实际业务数据,读取length永远返回0 - 三个分类卡片复用同一个空数组的长度属性,没有按照「优先级匹配+状态为待救援」的规则分别统计各分类的有效条目
- 没有绑定数据实时监听链路,后台数据变更后卡片数字不会自动刷新
修复实现
直接在分类页接入和列表页同源的Firestore数据流,一次拉取cases集合全量快照后,按各分类的筛选规则本地统计数量,既能保证数字和列表页展示的条目完全对齐,也能支持数据实时更新。小数据量场景下本地筛选性能足够,不需要多次发起查询。
修正后的分类页完整代码:
class CaseListCategory extends StatefulWidget { const CaseListCategory({Key? key}) : super(key: key); @override _CaseListCategoryState createState() => _CaseListCategoryState(); } class _CaseListCategoryState extends State<CaseListCategory> { /// Firestore案例集合引用,和列表页保持一致 final CollectionReference _cases = FirebaseFirestore.instance.collection('cases'); /// 统计指定优先级下、状态为待救援的案例总数 int _calcValidCaseCount(QuerySnapshot snapshot, String targetPriority) { return snapshot.docs.where((doc) { final caseData = doc.data() as Map<String, dynamic>; // 筛选条件和列表页完全对齐,避免数字和实际列表不符 return caseData['priority'] == targetPriority && caseData['status'] == "Waiting for rescue"; }).length; } @override Widget build(BuildContext context) { return Scaffold( body: Container( padding: const EdgeInsets.all(10), child: StreamBuilder<QuerySnapshot>( stream: _cases.snapshots(), builder: (context, snapshot) { // 数据加载时显示加载态 if (!snapshot.hasData) { return const Center(child: CircularProgressIndicator()); } // 提前计算三个分类的条目数 final criticalNum = _calcValidCaseCount(snapshot.data!, "Critical"); final moderateNum = _calcValidCaseCount(snapshot.data!, "Moderate"); final lowNum = _calcValidCaseCount(snapshot.data!, "Low"); return ListView( children: [ // 严重优先级卡片 GestureDetector( onTap: () => Navigator.of(context).push( MaterialPageRoute(builder: (context) => const CriticalCaseList()), ), child: Card( elevation: 10, color: Colors.red, child: Padding( padding: const EdgeInsets.symmetric(vertical: 30, horizontal: 10), child: Column( children: [ const Text( 'CRITICAL', style: TextStyle(letterSpacing: 1.0, fontSize: 20, fontWeight: FontWeight.bold), ), Text( "$criticalNum", style: const TextStyle(letterSpacing: 1.0, fontSize: 20, fontWeight: FontWeight.bold), ), ], ), ), ), ), // 中等优先级卡片 GestureDetector( onTap: () => Navigator.of(context).push( MaterialPageRoute(builder: (context) => const ModerateCaseList()), ), child: Card( elevation: 10, color: Colors.orange, child: Padding( padding: const EdgeInsets.symmetric(vertical: 30, horizontal: 10), child: Column( children: [ const Text( "MODERATE", style: TextStyle(letterSpacing: 1.0, fontSize: 20, fontWeight: FontWeight.bold), ), Text( "$moderateNum", style: const TextStyle(letterSpacing: 1.0, fontSize: 20, fontWeight: FontWeight.bold), ), ], ), ), ), ), // 低优先级卡片 GestureDetector( onTap: () => Navigator.of(context).push( MaterialPageRoute(builder: (context) => const LowCaseList()), ), child: Card( elevation: 10, color: Colors.yellow, child: Padding( padding: const EdgeInsets.symmetric(vertical: 30, horizontal: 10), child: Column( children: [ const Text( 'LOW', style: TextStyle(letterSpacing: 1.0, fontSize: 20, fontWeight: FontWeight.bold), ), Text( "$lowNum", style: const TextStyle(letterSpacing: 1.0, fontSize: 20, fontWeight: FontWeight.bold), ), ], ), ), ), ), ], ); }, ), ), ); } }
补充说明:如果后续cases集合数据量超过1000条,不建议继续使用拉全量本地筛选的方案,可以改用Firestore的
count()查询,按三个分类的筛选条件分别发起计数请求,减少不必要的流量消耗。如果修改了列表页的条目筛选规则,必须同步更新_calcValidCaseCount里的判断逻辑,避免卡片数字和实际列表条目数不一致。
内容的提问来源于stack exchange,提问作者mihab
相关产品推荐
相关产品推荐

