Flutter Hive热重启后获取数据触发类型转换错误
问题
在Hive Box中存储数据后,首次在FavoritesPage读取完全正常,但热重启应用后进入该页面会抛出类型转换错误。
错误信息
══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
抛出以下_CastError错误,发生在构建ValueListenableBuilder<Box>(dirty, state: _ValueListenableBuilderState<Box
>#b8b8b)时:
type 'List' is not a subtype of type 'List' in type cast
相关代码
FavoritesPage代码
class _FavoritesPageState extends State<FavoritesPage> { @override void initState() { super.initState(); //HandleFavorites.deleteAll(); } @override Widget build(BuildContext context) { return Scaffold( body: ValueListenableBuilder<Box<List<FavoritesSongs>>>( valueListenable: HandleFavorites.getFavoritesSongs().listenable(), builder: (context, fav, _) { final favorites = fav.values.toList().cast<List<FavoritesSongs>>(); return favorites.isEmpty ? const Center(child: Text('No Sounds Yet')) : Column( children: favorites.map((e) => buildContent(e)).toList()); }, ), ); } }
buildContent方法代码
Widget buildContent(List<FavoritesSongs> favoritesSongs) { if (favoritesSongs.isEmpty) { return const Center(child: Text('Empty')); } else { return Column( children: [ ListView.builder( scrollDirection: Axis.vertical, shrinkWrap: true, itemCount: favoritesSongs.length, itemBuilder: (BuildContext context, int index) { final fav = favoritesSongs[index]; return Text(fav.id); }, ), const Divider( height: 20, thickness: 2, color: Colors.black, ), ], ); } }
HandleFavorites类代码
class HandleFavorites { static Box<List<FavoritesSongs>> getFavoritesSongs() => Hive.box<List<FavoritesSongs>>(StaticWords.favorites); }
Favorites实体类代码
import 'package:hive/hive.dart'; part 'favorites_songs.g.dart'; @HiveType(typeId: 1, adapterName: "FavoritesSongsAdapter") class FavoritesSongs { FavoritesSongs({required this.id, required this.volume}); @HiveField(0) String id; @HiveField(1) double volume; } @HiveType(typeId: 2, adapterName: "FavoritesListAdapter") class FavoritesList extends HiveObject { FavoritesList({required this.listId, required this.listOfSounds}); @HiveField(0) String listId; @HiveField(1) List<FavoritesSongs> listOfSounds; }
Hive初始化代码(main.dart)
Future main() async { WidgetsFlutterBinding.ensureInitialized(); await Hive.initFlutter(); Hive.registerAdapter(FavoritesSongsAdapter()); Hive.openBox<List<FavoritesSongs>>(StaticWords.favorites); runApp(const Equable()); }
解决方案
问题根源在于直接用Box<List<FavoritesSongs>>存储列表,Hive无法正确序列化/反序列化嵌套泛型列表,热重启后丢失类型信息导致转换失败。应该使用你定义的FavoritesList类封装列表进行存储:
- 修改HandleFavorites类
class HandleFavorites { static Box<FavoritesList> getFavoritesSongs() => Hive.box<FavoritesList>(StaticWords.favorites); }
- 更新main.dart的Hive初始化逻辑
注册FavoritesListAdapter并打开对应类型的Box:
Future main() async { WidgetsFlutterBinding.ensureInitialized(); await Hive.initFlutter(); Hive.registerAdapter(FavoritesSongsAdapter()); Hive.registerAdapter(FavoritesListAdapter()); await Hive.openBox<FavoritesList>(StaticWords.favorites); runApp(const Equable()); }
- 调整FavoritesPage的ValueListenableBuilder
@override Widget build(BuildContext context) { return Scaffold( body: ValueListenableBuilder<Box<FavoritesList>>( valueListenable: HandleFavorites.getFavoritesSongs().listenable(), builder: (context, favBox, _) { final favorites = favBox.values.toList(); return favorites.isEmpty ? const Center(child: Text('No Sounds Yet')) : Column( children: favorites.map((favItem) => buildContent(favItem.listOfSounds)).toList()); }, ), ); }
- 存储数据时使用FavoritesList对象
添加收藏列表时,创建FavoritesList实例存入Box,而非直接存列表:
void addFavoritesList(String listId, List<FavoritesSongs> songs) { final box = HandleFavorites.getFavoritesSongs(); box.put(listId, FavoritesList(listId: listId, listOfSounds: songs)); }
修改后,Hive会通过生成的FavoritesListAdapter正确处理序列化和反序列化,热重启后不会丢失类型信息,类型转换错误即可解决。
内容的提问来源于stack exchange,提问作者ripouu
相关产品推荐
相关产品推荐

