Flutter中Firebase数据存入Double列表计算周均值时添加异常问题
Flutter Firebase数据处理异常:学生阅读页数转Double列表计算周均值失败
基于Flutter开发的应用中,从Firebase的students_data集合获取学生指定日期范围内的每日阅读页数数据,需要将这些数据存入Double类型列表后计算周均值,但在向列表添加数据的过程中出现异常。相关代码如下:
List<ModelData> students = []; for (var student in students) { FirebaseFirestore.instance .collection('students_data') .where('mail', isEqualTo: student.userID) .where( 'date', isGreaterThanOrEqualTo: startDate, ) .where('date', isLessThanOrEqualTo: finishDate) .get() .then((value2) { try { for (var i = 0; i < value2.docs.length; i++) { data.add( ModelData( date: value2.docs[i]['date'] ?? "", readingbookvalue: value2.docs[i]['readingbookvalue'] ?? "", mail: value2.docs[i]['mail'] ?? "", ), ); if (data[i].readingbookvalue == "") { double value = 0; setState(() { student.readingbooks?.add(value); }); } else { double value = double.parse(data[i].readingbookvalue ?? "0"); setState(() { student.readingbook?.add(value); }); } student.readingbook_average = student.readingbook!.reduce((a, b) => a + b) / student.readingbook!.length; } catch (e) { e.toString(); } }).whenComplete(() { setState(() { loading = false; }); }); } class ModelData{ String? date; String? readingbookvalue; int? mail; double? readingbook; List<double>? readingbook_average; ModelOgrenci({ this.readingbook, this.readingbook_average, }); }
核心问题点
- 模型类定义错误
- 构造函数名
ModelOgrenci与类名ModelData不匹配,导致实例化失败 - 字段类型逻辑混乱:
readingbook应定义为List<double>?(存储每日页数列表),当前错误设为double?readingbook_average应定义为double?(存储周均值),当前错误设为List<double>?mail是邮箱字符串,却定义为int?,类型完全不匹配
- 构造函数名
- 空安全未处理
student.readingbook?.add(value)中,若readingbook未初始化(为null),添加操作不会执行,后续调用reduce计算均值时触发空指针异常
- 逻辑冗余与时机错误
- 先将数据存入
data列表再读取,完全可以直接从Firebase文档快照获取数据,冗余操作易引发索引错误 - 在遍历文档的循环内部计算均值,此时数据未全部添加,结果不准确
- 先将数据存入
- 状态更新不合理
- 循环中多次调用
setState,频繁触发UI重建,影响性能
- 循环中多次调用
- 异常处理无效
catch块仅执行e.toString(),未打印异常信息,无法定位问题
修正后的代码实现
1. 修正模型类
class ModelData { String? date; String? readingbookvalue; String? mail; // 改为String类型匹配邮箱 List<double>? readingbook; // 存储每日阅读页数列表 double? readingbook_average; // 存储周均值 ModelData({ this.date, this.readingbookvalue, this.mail, this.readingbook, this.readingbook_average, }); }
2. 优化数据获取与处理逻辑
List<ModelData> students = []; bool loading = true; // 处理学生阅读数据的方法 void fetchStudentReadingData() async { setState(() { loading = true; }); for (var student in students) { // 提前初始化列表,避免空指针 student.readingbook ??= []; try { final querySnapshot = await FirebaseFirestore.instance .collection('students_data') .where('mail', isEqualTo: student.userID) .where('date', isGreaterThanOrEqualTo: startDate) .where('date', isLessThanOrEqualTo: finishDate) .get(); // 直接遍历文档快照处理数据 for (var doc in querySnapshot.docs) { final readingValueStr = doc['readingbookvalue'] ?? ""; double value; if (readingValueStr.isEmpty) { value = 0; } else { // 捕获数字解析异常,避免非数字字符串崩溃 try { value = double.parse(readingValueStr); } catch (e) { print("解析阅读页数失败: $e"); value = 0; } } student.readingbook!.add(value); } // 所有数据添加完成后计算均值 if (student.readingbook!.isNotEmpty) { final total = student.readingbook!.reduce((a, b) => a + b); student.readingbook_average = total / student.readingbook!.length; } else { student.readingbook_average = 0; // 无数据时均值设为0 } } catch (e) { print("获取学生数据失败: $e"); } } setState(() { loading = false; }); }
关键优化说明
- 用
async/await替代then链式调用,代码逻辑更清晰易读 - 提前初始化
readingbook列表,彻底避免空指针异常 - 直接从Firebase文档快照读取数据,移除冗余的
data列表操作 - 均值计算放在所有数据添加完成后,确保结果准确
- 增加数字解析异常捕获,避免非数字字符串导致应用崩溃
- 统一在所有数据处理完成后调用
setState,减少UI重建次数 - 完善异常打印,便于快速定位问题
内容的提问来源于stack exchange,提问作者Semih Kaya
相关产品推荐
相关产品推荐

