Flutter Hive存储Map<String, int>成功但读取报类型转换错误如何解决?
报错原因
Hive在序列化存储Map类型数据时,不会保留Map的泛型参数信息,所有Map结构读取时都会被默认反序列化为_InternalLinkedHashMap<dynamic, dynamic>类型。即便你在声明Box、打开Box时指定了Map<String, int>的泛型,Hive内部也不会自动完成类型校验和转换,直接赋值给Map<String, int>?类型的变量时就会触发类型不匹配的强转失败报错。
修复方案
你可以根据自己的业务场景选择以下任意一种方案修复:
方案1:读取时手动转换Map类型
无需修改存储逻辑,只需要调整读取代码,先拿到动态类型的Map再手动转成目标泛型即可,示例修改如下:// 读取数据时的逻辑调整 dynamic rawMap = hiveBox.get(matchKey); Map<String, int>? tm = rawMap?.map<String, int>((key, value) => MapEntry(key as String, value as int));如果你担心脏数据导致转换报错,可以在转换前增加类型校验逻辑。
方案2:注册自定义Adapter实现类型自动转换
给Map<String, int>类型自定义Hive序列化Adapter,注册后Hive会自动按照指定规则处理序列化/反序列化,完全保留泛型信息,不需要修改现有读写逻辑:- 定义Adapter:
class MapStringIntAdapter extends TypeAdapter<Map<String, int>> { // 取值为未被其他Adapter占用的id即可 @override final int typeId = 101; @override Map<String, int> read(BinaryReader reader) { int length = reader.readInt(); Map<String, int> result = {}; for (int i = 0; i < length; i++) { result[reader.readString()] = reader.readInt(); } return result; } @override void write(BinaryWriter writer, Map<String, int> obj) { writer.writeInt(obj.length); obj.forEach((key, value) { writer.writeString(key); writer.writeInt(value); }); } }- 打开Box前注册Adapter:
Hive.registerAdapter(MapStringIntAdapter()); await Hive.openBox<Map<String, int>>('SaveBetBox');注意:如果之前已经生成了缓存数据,切换方案前需要清空旧缓存,避免反序列化旧数据时报错。
方案3:封装HiveObject实体类存储
如果你的Map结构是固定的,可以定义一个继承自HiveObject的实体类,把Map的key作为类的属性存储,Hive会自动处理类型校验,不会出现泛型丢失问题。
内容的提问来源于stack exchange,提问作者Raj A
相关产品推荐
相关产品推荐

