You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter开发音乐播放器,Hive存储SongModel列表遇HiveError求助

问题解决:Hive无法保存SongModel类型的解决方案

错误原因很明确:Hive只能序列化基本数据类型(如int、String)和已通过@HiveType注解并注册适配器的自定义类。SongModel是on_audio_query包提供的第三方类,没有实现Hive的序列化规则,直接存入就会触发未知类型错误。

下面提供两种可行的解决方法:

方案一:将SongModel转换为自定义Hive实体类(推荐)

通过自定义一个与SongModel字段对应的Hive实体类,先完成数据转换再存入Hive,这种方法兼容性和可维护性最强。

  1. 创建自定义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,
    );
  }
}
  1. 生成适配器文件
    在终端运行命令,自动生成my_song.g.dart:
flutter packages pub run build_runner build
  1. 修改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);
}
  1. 在main函数中注册所有适配器
void main() async {
  await Hive.initFlutter();
  Hive.registerAdapter(AddedSongsAdapter());
  Hive.registerAdapter(MySongAdapter()); // 新增注册MySong的适配器
  await Hive.openBox<AddedSongs>('AddedSongBox');
  runApp(const MyApp());
}
  1. 保存数据时完成类型转换
// 假设你有原始的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手动实现适配器,但需要准确对应类的所有字段,后续包更新时需同步维护。

  1. 编写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 ?? "");
    // 写入其他必填字段
  }
}
  1. 在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 07:33:35