在Flutter中使用Hive本地存储CategoryModel列表的方法
解决Hive存储CategoryModel列表失败的问题
一、配置依赖
先确保pubspec.yaml中添加Hive相关依赖:
dependencies: flutter: sdk: flutter hive: ^2.2.3 hive_flutter: ^1.1.0 dev_dependencies: flutter_test: sdk: flutter build_runner: ^2.4.4 hive_generator: ^1.1.5
二、处理自定义类的序列化
Hive无法直接存储自定义对象和特殊类型(如File、IconData、Color等),需要通过注解生成适配器,并将特殊类型转换为可序列化的基础类型:
1. 处理枚举类(CategoryType)
如果CategoryType是枚举,添加Hive注解标记:
import 'package:hive/hive.dart'; import 'package:flutter/material.dart'; import 'dart:io'; @HiveType(typeId: 0) enum CategoryType { @HiveField(0) type1, @HiveField(1) type2, // 补充你的实际枚举项 }
2. 处理ListTileData(自定义类)
如果ListTileData是你定义的类,同样需要添加Hive注解:
@HiveType(typeId: 1) class ListTileData { @HiveField(0) final String title; // 补充你的其他字段 ListTileData({required this.title}); }
3. 修改CategoryModel类
将特殊类型转换为可序列化的基础类型,添加Hive注解:
@HiveType(typeId: 2) class CategoryModel { CategoryModel({ required this.type, IconData? iconData, List<File>? imageList, this.notesText, IconData? reminderIcon, this.reminderText, this.reminderTimeText, this.titel, Color? color, this.rawList, this.reminderwidth, this.backgroundImage, Color? reminderColor, this.selectedTile, this.selectedimage, this.path, this.crossCount, Duration? duration, this.colorSelected, this.isSelected = false, this.checkScreen = false, this.notesController, }) { // 初始化特殊类型的转换字段 this.iconData = iconData; this.imageList = imageList; this.reminderIcon = reminderIcon; this.color = color; this.reminderColor = reminderColor; this.duration = duration; } @HiveField(0) final CategoryType type; @HiveField(1) String? titel; // IconData 转换存储:存codePoint和fontFamily @HiveField(2) int? _iconDataCodePoint; @HiveField(3) String? _iconDataFontFamily; IconData? get iconData { if (_iconDataCodePoint == null || _iconDataFontFamily == null) return null; return IconData(_iconDataCodePoint!, fontFamily: _iconDataFontFamily); } set iconData(IconData? value) { _iconDataCodePoint = value?.codePoint; _iconDataFontFamily = value?.fontFamily; } @HiveField(4) String? notesText; // List<File> 转换存储:存文件路径列表 @HiveField(5) List<String>? _imagePaths; List<File>? get imageList { if (_imagePaths == null) return null; return _imagePaths!.map((path) => File(path)).toList(); } set imageList(List<File>? value) { _imagePaths = value?.map((file) => file.path).toList(); } // ReminderIcon 同IconData处理 @HiveField(6) int? _reminderIconCodePoint; @HiveField(7) String? _reminderIconFontFamily; IconData? get reminderIcon { if (_reminderIconCodePoint == null || _reminderIconFontFamily == null) return null; return IconData(_reminderIconCodePoint!, fontFamily: _reminderIconFontFamily); } set reminderIcon(IconData? value) { _reminderIconCodePoint = value?.codePoint; _reminderIconFontFamily = value?.fontFamily; } @HiveField(8) String? reminderText; @HiveField(9) String? reminderTimeText; // Color 转换存储:存颜色的int值 @HiveField(10) int? _colorValue; Color? get color { if (_colorValue == null) return null; return Color(_colorValue!); } set color(Color? value) { _colorValue = value?.value; } @HiveField(11) List<ListTileData>? rawList; @HiveField(12) double? reminderwidth; @HiveField(13) String? backgroundImage; // ReminderColor 同Color处理 @HiveField(14) int? _reminderColorValue; Color? get reminderColor { if (_reminderColorValue == null) return null; return Color(_reminderColorValue!); } set reminderColor(Color? value) { _reminderColorValue = value?.value; } @HiveField(15) int? selectedTile; @HiveField(16) int? selectedimage; @HiveField(17) bool? checkScreen; @HiveField(18) String? notesController; @HiveField(19) int? crossCount; @HiveField(20) String? path; // Duration 转换存储:存毫秒数 @HiveField(21) int? _durationMilliseconds; Duration? get duration { if (_durationMilliseconds == null) return null; return Duration(milliseconds: _durationMilliseconds!); } set duration(Duration? value) { _durationMilliseconds = value?.inMilliseconds; } @HiveField(22) int? colorSelected; @HiveField(23) bool? isSelected; }
三、生成适配器
在项目根目录的终端运行以下命令,生成所有自定义类的Hive适配器:
flutter packages pub run build_runner build
四、初始化Hive并注册适配器
在main函数中初始化Hive,注册所有适配器并打开存储box:
import 'package:flutter/material.dart'; import 'package:hive/hive.dart'; import 'package:hive_flutter/hive_flutter.dart'; import 'path/to/your/model/file.dart'; // 替换为你的CategoryModel文件路径 void main() async { await Hive.initFlutter(); // 注册所有适配器 Hive.registerAdapter(CategoryModelAdapter()); Hive.registerAdapter(CategoryTypeAdapter()); Hive.registerAdapter(ListTileDataAdapter()); // 打开存储CategoryModel的box await Hive.openBox<CategoryModel>('categories_box'); runApp(const MyApp()); }
五、存储和读取数据
现在可以正常存储和读取allCategory列表了:
// 获取存储box final categoriesBox = Hive.box<CategoryModel>('categories_box'); // 存储allCategory列表 await categoriesBox.clear(); // 可选,清空旧数据 await categoriesBox.addAll(allCategory); // 读取存储的列表 List<CategoryModel> storedCategories = categoriesBox.values.toList();
常见问题排查
- 未注册适配器:打开box前必须注册所有自定义类的Adapter,否则会报错
- 特殊类型未处理:Hive仅支持基础类型、List/Map和Hive注解的自定义类,像
File、IconData这类必须转换为可序列化类型 - TypeId冲突:每个
@HiveType的typeId必须唯一,不能与其他类重复 - 字段未加
@HiveField:所有需要存储的字段必须添加@HiveField注解,且index不能重复
内容的提问来源于stack exchange,提问作者Satvik Donda
相关产品推荐
相关产品推荐

