使用通用基类HiveCacheOperation初始化不同模型类时触发类型不匹配异常的问题求助
使用通用基类HiveCacheOperation初始化不同模型类时触发类型不匹配异常的问题求助
看起来你遇到的问题根源出在Hive适配器注册的方式错误,以及没有为不同模型类区分正确的Hive类型标识或独立Box实例。让我一步步帮你分析并解决:
问题核心分析
先看你HiveCacheManager.init方法里的这段错误代码:
Hive.registerAdapter('${item.runtimeType}', item.fromDynamicJson);
Hive的registerAdapter API要求第一个参数是TypeAdapter的实例,第二个参数是可选的整数类型ID;而你传入了字符串和fromJson方法,完全不符合规范。这种错误的注册方式会导致Hive无法正确识别不同模型的类型,反序列化时就会出现"预期A类型却得到B类型"的异常。
解决方案步骤
- 为每个缓存模型生成合法的Hive TypeAdapter
Hive必须依赖TypeAdapter来处理自定义类的序列化/反序列化,推荐用hive_generator自动生成:
- 给每个模型类添加Hive注解,确保
typeId唯一:import 'package:hive/hive.dart'; @HiveType(typeId: 0) // 唯一整数ID,每个模型不能重复 class UserCacheModel extends CacheModel { @HiveField(0) // 字段序号,从0开始 final String? userId; UserCacheModel({this.userId}); UserCacheModel.empty() : userId = null; static UserCacheModel fromDynamicJson(Map<String, dynamic> json) => UserCacheModel(userId: json['userId']); } @HiveType(typeId: 1) class UserTokenCacheModel extends CacheModel { @HiveField(0) final String? token; UserTokenCacheModel({this.token}); UserTokenCacheModel.empty() : token = null; static UserTokenCacheModel fromDynamicJson(Map<String, dynamic> json) => UserTokenCacheModel(token: json['token']); } - 运行命令生成Adapter文件:
执行后会生成flutter pub run build_runner builduser_cache_model.g.dart和user_token_cache_model.g.dart两个文件,里面包含自动生成的TypeAdapter实现。
- 修正HiveCacheManager的初始化逻辑
现在要正确注册生成的Adapter,同时确保每个模型可以使用独立的Box:
final class HiveCacheManager extends CacheManager { /// [path] is the path to the directory /// where the Hive database files are stored. HiveCacheManager({super.path}); @override Future<void> init({required List<CacheModel> items}) async { final documentPath = path ?? (await getApplicationDocumentsDirectory()).path; Hive.defaultDirectory = documentPath; // 注册自动生成的TypeAdapter Hive.registerAdapter(UserCacheModelAdapter()); Hive.registerAdapter(UserTokenCacheModelAdapter()); // 提前打开需要的Box,避免后续重复打开 await Future.wait([ Hive.openBox<UserCacheModel>('user_cache_box'), Hive.openBox<UserTokenCacheModel>('token_cache_box'), ]); } @override void remove() { Hive.deleteAllBoxesFromDisk(); } }
- 调整HiveCacheOperation,绑定独立Box
让通用操作类针对每个模型使用专属的Box,避免类型混淆:
class HiveCacheOperation<T> { late final Box<T> _box; // 初始化时传入对应模型的Box名称 Future<void> init(String boxName) async { _box = await Hive.openBox<T>(boxName); } // 示例缓存操作方法 Future<void> save(String key, T data) => _box.put(key, data); T? get(String key) => _box.get(key); Future<void> delete(String key) => _box.delete(key); }
- 修正ProductCache的初始化流程
确保每个缓存操作实例绑定对应的Box:
final class ProductCache { ProductCache({required CacheManager cacheManager}) : _cacheManager = cacheManager; final CacheManager _cacheManager; Future<void> init() async { await _cacheManager.init( items: [ UserCacheModel.empty(), UserTokenCacheModel.empty(), ], ); // 初始化每个缓存操作的专属Box await userCacheOperation.init('user_cache_box'); await userTokenCacheOperation.init('token_cache_box'); } late final HiveCacheOperation<UserCacheModel> userCacheOperation = HiveCacheOperation<UserCacheModel>(); late final HiveCacheOperation<UserTokenCacheModel> userTokenCacheOperation = HiveCacheOperation<UserTokenCacheModel>(); }
为什么会触发类型不匹配异常?
你之前的错误注册方式让Hive无法建立模型类与反序列化逻辑的正确关联,当从Box中读取数据时,Hive无法区分UserCacheModel和UserTokenCacheModel的序列化数据,错误地将其中一种类型的数据反序列化成了另一种类型,最终抛出类型不匹配的异常。
按照上述步骤修正后,应该就能解决这个问题了。
备注:内容来源于stack exchange,提问作者cagatay celik
相关产品推荐
相关产品推荐

