Flutter开发音乐播放器,Hive存储SongModel列表遇HiveError求助
问题解决:Hive无法保存SongModel类型的解决方案
错误原因很明确:Hive只能序列化基本数据类型(如int、String)和已通过@HiveType注解并注册适配器的自定义类。SongModel是on_audio_query包提供的第三方类,没有实现Hive的序列化规则,直接存入就会触发未知类型错误。
下面提供两种可行的解决方法:
方案一:将SongModel转换为自定义Hive实体类(推荐)
通过自定义一个与SongModel字段对应的Hive实体类,先完成数据转换再存入Hive,这种方法兼容性和可维护性最强。
- 创建自定义Hive实体类
MySong
import 'package:hive_flutter/hive_flutter.dart'; import 'package:on_audio_query/on_audio_query.dart'; part 'my_song.g.dart'; @HiveType(typeId: 4) // 确保typeId与其他实体类不重复 class MySong { @HiveField(0) final int id; @HiveField(1) final String title; @HiveField(2) final String artist; @HiveField(3) final String uri; MySong({ required this.id, required this.title, required this.artist, required this.uri, }); // 从SongModel转换为MySong factory MySong.fromSongModel(SongModel song) { return MySong( id: song.id, title: song.title, artist: song.artist ?? "未知艺术家", uri: song.uri ?? "", ); } // 从MySong转换回SongModel(如果需要还原使用) SongModel toSongModel() { return SongModel( id: id, title: title, artist: artist, uri: uri, ); } }
- 生成适配器文件
在终端运行命令,自动生成my_song.g.dart:
flutter packages pub run build_runner build
- 修改
AddedSongs类的字段类型
import 'package:hive_flutter/hive_flutter.dart'; import 'my_song.dart'; part 'added_songs.g.dart'; @HiveType(typeId: 3) class AddedSongs { @HiveField(0) // 字段id建议从0开始统一规范,之前的4也可保留但尽量统一 List<MySong> songs; AddedSongs(this.songs); }
- 在main函数中注册所有适配器
void main() async { await Hive.initFlutter(); Hive.registerAdapter(AddedSongsAdapter()); Hive.registerAdapter(MySongAdapter()); // 新增注册MySong的适配器 await Hive.openBox<AddedSongs>('AddedSongBox'); runApp(const MyApp()); }
- 保存数据时完成类型转换
// 假设你有原始的SongModel列表 List<SongModel> originalSongs = [...]; // 转换为MySong列表 List<MySong> convertedSongs = originalSongs.map((song) => MySong.fromSongModel(song)).toList(); // 存入Hive final box = Hive.box<AddedSongs>('AddedSongBox'); box.put('saved_songs', AddedSongs(convertedSongs));
方案二:为SongModel手动编写TypeAdapter
如果不想创建自定义类,可以为SongModel手动实现适配器,但需要准确对应类的所有字段,后续包更新时需同步维护。
- 编写
SongModelAdapter类
import 'package:hive/hive.dart'; import 'package:on_audio_query/on_audio_query.dart'; class SongModelAdapter extends TypeAdapter<SongModel> { @override final int typeId = 5; // 确保typeId全局唯一 @override SongModel read(BinaryReader reader) { // 按顺序读取字段,需与write方法的顺序完全一致 return SongModel( id: reader.readInt(), title: reader.readString(), artist: reader.readString(), uri: reader.readString(), // 补充SongModel构造函数中所有必填字段 ); } @override void write(BinaryWriter writer, SongModel obj) { // 按顺序写入字段 writer.writeInt(obj.id); writer.writeString(obj.title); writer.writeString(obj.artist ?? ""); writer.writeString(obj.uri ?? ""); // 写入其他必填字段 } }
- 在main函数中注册适配器
void main() async { await Hive.initFlutter(); Hive.registerAdapter(AddedSongsAdapter()); Hive.registerAdapter(SongModelAdapter()); // 注册SongModel的适配器 await Hive.openBox<AddedSongs>('AddedSongBox'); runApp(const MyApp()); }
内容的提问来源于stack exchange,提问作者Sahand
相关产品推荐
相关产品推荐

