如何在Flutter的StreamBuilder中获取并处理Cloud Firestore的Stream返回数据
问题修正方案
核心错误原因
你当前的判断逻辑存在严重的类型不匹配问题:
Stream<QuerySnapshot>返回的snapshot.data是Firestore的QuerySnapshot类型对象,存储的是符合你查询条件的所有文档集合,不是直接的字段键值对- 你将
AsyncSnapshot类型的snapshot直接和{'Stufe', 1}这个Set集合比较,二者类型完全不同,判断永远返回false
正确的数据获取逻辑
你需要先从QuerySnapshot中取出文档列表,再读取文档内的字段:
- 用
QuerySnapshot.docs获取所有符合条件的DocumentSnapshot数组 - 从每个
DocumentSnapshot中通过data()方法或者get(字段名)方法读取字段值 - 由于你在查询时已经通过
where('Stufe', isEqualTo: 1)做了过滤,所有匹配到的文档的Stufe字段肯定是1,无需额外判断,只需要判断是否有匹配到的文档即可
其他代码问题
- 缺少异常处理逻辑:Stream加载失败时没有错误提示,用户会一直看到加载动画
- 你渲染
ListView时使用的Stufen变量没有和Firestore返回的实时数据绑定,拿到的永远是本地旧数据 - 没有判断匹配文档为空的情况,空数据时
ListView会显示空白
修正后代码示例
你只需要替换StreamBuilder的builder部分即可:
builder: (context, AsyncSnapshot<QuerySnapshot> snapshot) { // 异常状态处理 if (snapshot.hasError) { return Center(child: Text('数据加载失败:${snapshot.error.toString()}')); } // 加载状态处理 if (!snapshot.hasData) { return Center(child: CircularProgressIndicator()); } // 获取匹配到的所有文档 final matchedDocs = snapshot.data!.docs; // 有匹配到Stufe=1的文档时返回对应页面 if (matchedDocs.isNotEmpty) { // 如果你需要读取文档其他字段,可以用以下方式: // final firstDocData = matchedDocs.first.data() as Map<String, dynamic>; // int stufeValue = firstDocData['Stufe'] as int; return ToDo1F(); } // 将Firestore文档数据转换为你需要的Stufen Map Map<String, dynamic> Stufen = {}; for (var doc in matchedDocs) { Stufen[doc.id] = doc.data(); } // 渲染列表 return ListView.separated( separatorBuilder: (BuildContext context, int index) => SizedBox(height: 10), padding: EdgeInsets.all(10), itemCount: Stufen.length, itemBuilder: (context, i) { String key = Stufen.keys.elementAt(i); return StufenItem( key, Stufen[key]!, () => toggleDone(key), () => select(key), ); } ); }
内容的提问来源于stack exchange,提问作者Lars
相关产品推荐
相关产品推荐

