You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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,
  });
}

核心问题点

  1. 模型类定义错误
    • 构造函数名ModelOgrenci与类名ModelData不匹配,导致实例化失败
    • 字段类型逻辑混乱:
      • readingbook应定义为List<double>?(存储每日页数列表),当前错误设为double?
      • readingbook_average应定义为double?(存储周均值),当前错误设为List<double>?
      • mail是邮箱字符串,却定义为int?,类型完全不匹配
  2. 空安全未处理
    • student.readingbook?.add(value)中,若readingbook未初始化(为null),添加操作不会执行,后续调用reduce计算均值时触发空指针异常
  3. 逻辑冗余与时机错误
    • 先将数据存入data列表再读取,完全可以直接从Firebase文档快照获取数据,冗余操作易引发索引错误
    • 在遍历文档的循环内部计算均值,此时数据未全部添加,结果不准确
  4. 状态更新不合理
    • 循环中多次调用setState,频繁触发UI重建,影响性能
  5. 异常处理无效
    • 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 14:25:34