Flutter中Dart将Stream<List<double>>转List<double>报bad state错误如何解决
问题根因与修复方案
错误触发的3个核心原因
- 映射逻辑缺失返回值:
_DeadliftWeightsList中对文档做映射的回调函数仅创建了Weights对象,但没有显式return,最终生成的weights列表全为null,后续NormalizedData中用!强制解包null直接触发异常。 - 同步异步逻辑混淆:
Stream是异步数据源,listen的回调会在未来数据到达时才执行,你在DLWeights中同步返回的weights列表在返回时为空,若后续逻辑依赖列表有值(比如调用reduce、访问首个元素等操作)就会触发bad state错误。 - 边界条件缺失:如果查询到的文档为空、或者所有重量值相等,
NormalizedData中调用reduce、执行除法运算时会直接抛出bad state、除零错误。
修复后的完整代码
1. 修复_DeadliftWeightsList映射逻辑
List<double> _DeadliftWeightsList(QuerySnapshot snapshot){ List <Weights?> weights = snapshot.docs.map((doc){ // 补全return语句,返回创建的Weights对象 return Weights( date: doc.get('date') ?? DateTime.now(), weight: doc.get('deadLiftWeight') ?? 0); }).toList(); final List<double> normalized = NormalizedData(weights); return normalized; }
2. 修复NormalizedData边界判断
List<double> NormalizedData (List<Weights?> weights) { // 过滤null值,避免空指针 final List<int> array = weights.whereType<Weights>().map((e) => e.weight).toList(); // 空列表直接返回空,避免reduce触发bad state if(array.isEmpty) return []; final lower = array.reduce(min); final upper = array.reduce(max); // 最值相等时直接返回等长的0值列表,避免除零错误 if(upper == lower) { return List.filled(array.length, 0); } final List<double> normalized = []; for(var i = 0 ; i < array.length; i++){ normalized.add((array[i] - lower) / (upper - lower)); } return normalized; }
3. 修复DLWeights异步逻辑
如果需要实时监听数据变化,直接返回Stream,UI层用StreamBuilder消费即可:
Stream<List<double>> DLWeights() { return usersCollection.snapshots() .map(_DeadliftWeightsList); } // UI层使用示例 // StreamBuilder<List<double>>( // stream: DLWeights(), // builder: (context, snapshot) { // if(snapshot.hasData) { // final weights = snapshot.data!; // // 基于weights渲染对应UI // } // return CircularProgressIndicator(); // } // )
如果仅需要获取一次当前的重量数据,改为返回Future:
Future<List<double>> getDLWeightsOnce() async { final snapshot = await usersCollection.get(); return _DeadliftWeightsList(snapshot); } // 调用时用await接收值即可: // final weights = await getDLWeightsOnce();
内容的提问来源于stack exchange,提问作者Something You
相关产品推荐
相关产品推荐

