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

Hive持久化下SemesterModel的note字段二次重启应用后丢失的问题排查与解决

Hive持久化下SemesterModel的note字段二次重启应用后丢失的问题排查与解决

看起来你遇到的是Hive持久化中常见的字段未被正确序列化的问题,我来帮你拆解原因并给出解决方案:

问题核心原因

你的SemesterModel继承了HiveObject,Hive对这类对象的持久化完全依赖自动生成的.g.dart适配器文件,而不是你自己实现的toJson/fromJson方法。你添加了note字段并标记为@HiveField(8),但如果没有重新生成适配器,Hive的序列化逻辑里根本不会处理这个字段——这就导致你修改note后调用box.put时,Hive并没有把note的新值写入本地存储。第一次重启能看到note大概率是内存临时数据或测试场景的巧合,第二次冷启动时,Hive读取的是不包含note的旧持久化数据,所以note回到了默认的空字符串。

分步解决方案

1. 重新生成Hive适配器文件

这是最关键的一步,必须让Hive通过适配器识别新添加的note字段。在终端中运行以下命令:

flutter pub run build_runner build --delete-conflicting-outputs

这个命令会删除旧的适配器文件,重新生成包含所有最新字段(包括note)的新适配器。

2. 验证适配器是否正确包含note字段

打开semester_model.g.dart,找到SemesterModelAdapter类,检查其中的write和read方法:

  • write方法中应该有一行:writer.writeString(8, obj.note);
  • read方法中应该有一行:note: reader.readString(8),
    如果能找到这些代码,说明适配器已经正确识别了note字段。

3. 处理旧数据迁移(可选但推荐)

如果你的应用已经有用户在使用(或者本地有旧的测试数据),需要给旧数据补充note的默认值,避免读取异常。在初始化Hive的代码中修改openBox的逻辑:

await Hive.initFlutter();
// 先注册所有适配器(必须在openBox之前)
Hive.registerAdapter(SemesterModelAdapter());
Hive.registerAdapter(StudentModelAdapter());
Hive.registerAdapter(CourseModelAdapter());

// 打开Box时添加迁移逻辑
final box = await Hive.openBox<StudentModel>('default',
  migration: {
    // 假设旧Box版本是1,新版本是2(根据实际情况调整)
    1: (oldBox, newBox) {
      for (final key in oldBox.keys) {
        final oldStudent = oldBox.get(key) as StudentModel;
        // 为每个旧的SemesterModel补充note默认值
        final newStudent = StudentModel(
          cgpa: oldStudent.cgpa,
          totalCredits: oldStudent.totalCredits,
          semesters: oldStudent.semesters.map((oldSem) => SemesterModel(
            name: oldSem.name,
            gpa: oldSem.gpa,
            courses: oldSem.courses,
            selected: oldSem.selected,
            cgpaOriginal: oldSem.cgpaOriginal,
            cgpaChanged: oldSem.cgpaChanged,
            attemptedCredits: oldSem.attemptedCredits,
            earnedCredits: oldSem.earnedCredits,
            note: '', // 给旧数据设置默认空字符串
          )).toList(),
        );
        newBox.put(key, newStudent);
      }
    },
  },
);

4. 确认持久化逻辑正确性

你当前的saveSemesterNote方法逻辑是对的,不需要修改:

void saveSemesterNote(int semesterIndex, String updatedNote) {
  student.semesters[semesterIndex].note = updatedNote;
  box.put('default', student);
  emit(
    state.copyWith(semesters: List<SemesterModel>.from(student.semesters)),
  );
}

只要适配器正确,Hive就会把note的修改值一起持久化到本地。

额外注意事项

  • 每次修改Hive模型的字段(添加、删除、调整@HiveField索引)后,必须重新运行build_runner命令,否则会出现各种持久化异常。
  • 不要混淆Hive的适配器序列化和自定义的toJson/fromJson:前者是Hive持久化的核心,后者只适用于你自己的JSON场景(比如和后端交互),两者完全独立。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.08 08:13:04