Flutter Hive重启报错:List<dynamic>无法转为List<Bookingday>?
问题原因及解决方案
核心原因
Hive 对泛型列表的序列化支持有限:同一会话内,列表中的 Bookingday 对象仍在内存中,类型信息完整,所以读取时能直接识别;但重启APP后,Hive从磁盘读取数据时,会把存储的列表解析为 List<dynamic>,无法自动转换为 List<Bookingday>——因为Hive的类型适配器(TypeAdapter)是针对单个自定义对象设计的,而非列表本身。
解决方案
方案1:用包装类封装列表(推荐)
创建一个包含 List<Bookingday> 的包装类,给该类生成Hive类型适配器,让Hive能正确序列化/反序列化整个列表结构。
- 定义包装类
BookingWeek并添加Hive注解
import 'package:hive/hive.dart'; import 'bookingday.dart'; part 'booking_week.g.dart'; @HiveType(typeId: 1) // 确保typeId不与其他类冲突 class BookingWeek { @HiveField(0) List<Bookingday> days; BookingWeek({required this.days}); }
- 确保
Bookingday已配置Hive注解和适配器
import 'package:hive/hive.dart'; part 'bookingday.g.dart'; @HiveType(typeId: 0) class Bookingday { @HiveField(0) DateTime day; @HiveField(1) bool parkingSlotReserved; @HiveField(2) int capacityCounter; @HiveField(3) int maxCapacity; Bookingday({ required this.day, required this.parkingSlotReserved, required this.capacityCounter, required this.maxCapacity, }); }
- 生成适配器并注册
运行命令生成适配器:
flutter packages pub run build_runner build
在 main.dart 中注册适配器并打开Box:
void main() async { await Hive.initFlutter(); Hive.registerAdapter(BookingdayAdapter()); Hive.registerAdapter(BookingWeekAdapter()); await Hive.openBox<BookingWeek>(bookingDayBoxName); runApp(MyApp()); }
- 修改DAO的读写逻辑
Box<BookingWeek> box = Hive.box<BookingWeek>(bookingDayBoxName); List<Bookingday> getStoredWeek(DateTime firstJan, DateTime date) { String key = getCalenderWeek(firstJan, date); try { BookingWeek? week = box.get(key); if (week != null) { bookingdays = week.days; return week.days; } else { List<DateTime> weekDates = getWeek(dateNow); return List.generate( weekDates.length, (index) => Bookingday( day: weekDates[index], parkingSlotReserved: false, capacityCounter: 0, maxCapacity: 4, ), ); } } catch (e) { print(e); } return bookingdays; } // 存储方法也要对应修改 void saveWeek(DateTime firstJan, DateTime date, List<Bookingday> days) { String key = getCalenderWeek(firstJan, date); box.put(key, BookingWeek(days: days)); }
方案2:手动转换列表(应急用)
如果不想修改结构,可以在读取时手动将 List<dynamic> 转换为 List<Bookingday>,但这种方式风险较高(若数据损坏会抛出类型转换异常):
List<Bookingday>? bookList = (boxList.get(key) as List<dynamic>?)?.map((item) => item as Bookingday).toList();
内容的提问来源于stack exchange,提问作者Yusaku Goldbach
相关产品推荐
相关产品推荐

