Hive报错:'Null'无法转换为'String'类型的问题求助
问题描述
我在学习Hive时,基于教程和示例代码做了修改。原代码运行正常,我在Person模型中新增了一个必填的surname字段:
@HiveType(typeId: 1) class Person { @HiveField(0) final String name; @HiveField(1) final String country; @HiveField(2) final String surname; // 新增实验字段 Person({ required this.name, required this.country, required this.surname, // 新增实验字段 }); }
执行生成命令:
dart run build_runner build --delete-conflicting-outputs
运行应用时出现错误:
E/flutter (26138): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: type 'Null' is not a subtype of type 'String' in type cast E/flutter (26138): #0 PersonAdapter.read (package:enemies_list/models/person.g.dart:22:26) E/flutter (26138): #1 BinaryReaderImpl.read (package:hive/src/binary/binary_reader_impl.dart:328:33) E/flutter (26138): #2 BinaryReaderImpl.readFrame (package:hive/src/binary/binary_reader_impl.dart:276:26) E/flutter (26138): #3 FrameHelper.framesFromBytes (package:hive/src/binary/frame_helper.dart:21:26) E/flutter (26138): #4 FrameIoHelper.framesFromFile (package:hive/src/io/frame_io_helper.dart:42:12) E/flutter (26138): <asynchronous suspension> E/flutter (26138): #5 StorageBackendVm.initialize (package:hive/src/backend/vm/storage_backend_vm.dart:86:11) E/flutter (26138): <asynchronous suspension> E/flutter (26138): #6 HiveImpl._openBox (package:hive/src/hive_impl.dart:111:9) E/flutter (26138): <asynchronous suspension> E/flutter (26138): #7 HiveImpl.openBox (package:hive/src/hive_impl.dart:142:12) E/flutter (26138): <asynchronous suspension> E/flutter (26138): #8 main (package:enemies_list/main.dart:13:3) E/flutter (26138): <asynchronous suspension>
我已经修改了所有需要新增该字段的文件,仅新增一个字段却报错,请问原因是什么?
问题原因及解决办法
核心原因
你的Hive盒子中已经存储了旧版本的Person数据(没有surname字段),新增必填的surname字段后,Hive读取旧数据时该字段的值为Null,但模型要求它是必填的非空String,类型转换失败触发报错。
解决办法
- 清空旧数据:卸载应用后重新安装,或者直接删除Hive的存储文件(Android路径为
/data/data/你的包名/files/hive/,iOS在应用沙盒的Documents目录下)。 - 兼容旧数据:若需要保留旧数据,可修改模型让
surname字段可空,或给它设置默认值:
修改后重新执行// 方案1:改为可空类型 @HiveField(2) final String? surname; // 方案2:设置默认值 @HiveField(2) final String surname; Person({ required this.name, required this.country, String? surname, }) : surname = surname ?? '';dart run build_runner build --delete-conflicting-outputs生成新的适配器文件。 - 规范版本迁移:如果需要更严谨的版本管理,可给模型设置
adapterVersion,并在打开盒子时添加迁移逻辑:
打开盒子时处理版本差异:@HiveType(typeId: 1, adapterVersion: 2) // 升级版本号 class Person { // ...字段定义 }await Hive.openBox<Person>('persons', migration: (oldBox, newBox) { if (oldBox.adapterVersion < 2) { for (var key in oldBox.keys) { var oldPerson = oldBox.get(key); newBox.put(key, Person( name: oldPerson.name, country: oldPerson.country, surname: '', // 给旧数据补充默认值 )); } } });
内容的提问来源于stack exchange,提问作者Texter
相关产品推荐
相关产品推荐

