使用Hive持久化日历数据时触发未处理异常的原因排查
问题:Hive持久化日历数据启动时触发类型转换异常
启动程序时触发如下错误:
[ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: type 'Null' is not a subtype of type 'bool' in type cast
模型类代码
@HiveType(typeId: 1) class Event extends HiveObject { @HiveField(0) late String title; @HiveField(1) late DateTime eventDateTime; @HiveField(2) bool wholeDayEvent; Event({ required this.title, required this.eventDateTime, required this.wholeDayEvent, }); @override String toString() => title; }
展示组件build方法代码
Expanded( child: ValueListenableBuilder<Box<Event>>( valueListenable: Boxes.getEvents().listenable(), builder: (context, box, _) { final events = box.values.toList().cast<Event>(); return ListView.builder( itemCount: events.length, itemBuilder: (context, index) { return Container( margin: const EdgeInsets.symmetric( horizontal: 12.0, vertical: 4.0, ), decoration: BoxDecoration( border: Border.all(), borderRadius: BorderRadius.circular(12.0), ), child: ListTile( onTap: () => print('${box.values}'), title: Text('${box.values}'), ), ); }, ); }, ), ),
异常原因及解决方法
异常原因
- 旧数据兼容问题:如果Hive Box中已存储的Event数据没有
wholeDayEvent字段,或者该字段值为null,Hive反序列化时会返回null,但模型类中wholeDayEvent是不可为null的bool类型,强行转换null为bool就会触发这个异常。 - 模型字段定义问题:
wholeDayEvent既没有用late修饰,也没有设置默认值,当Hive无法读取到该字段值时,会尝试赋值null,而该字段不允许为null,进而引发错误。
解决方法
方法1:兼容旧数据并更新模型
- 备份现有Hive数据(可选但推荐)。
- 修改模型类,给
wholeDayEvent设置构造函数默认值:
@HiveType(typeId: 1) class Event extends HiveObject { @HiveField(0) late String title; @HiveField(1) late DateTime eventDateTime; @HiveField(2) bool wholeDayEvent; Event({ required this.title, required this.eventDateTime, this.wholeDayEvent = false, // 添加默认值 }); @override String toString() => title; }
- 启动APP,遍历Box中的所有数据,为缺少
wholeDayEvent的条目赋值默认值(比如false),然后重新保存。 - 确认所有数据更新完成后,可根据需求将模型改回不可空类型。
方法2:清空旧数据(适合测试阶段)
如果处于开发测试阶段,无需保留旧数据,可直接调用box.clear()清空Box中的数据,或者删除Hive的存储文件,重启APP后新存储的数据都会包含wholeDayEvent字段,不会再出现null转换问题。
内容的提问来源于stack exchange,提问作者DanJayLee79
相关产品推荐
相关产品推荐

