如何从Hive Box中检索指定字段(标题与价格)?
问题原因
你把Recipe对象转成JSON字符串存入Hive,但取出时直接把字符串当成了可索引的对象/Map,用p[1]会取字符串的第二个字符(比如JSON字符串开头是{"url":...,p[1]就是"U"),这才导致错误结果。
解决方案
有两种可行的处理方式,推荐第一种更符合Hive使用规范的方案:
方案一:直接存储Recipe对象(推荐)
Hive支持存储自定义对象,无需转成JSON字符串,这样存取更直观:
配置Hive自定义对象支持
- 在
pubspec.yaml添加依赖:dependencies: hive: ^2.2.3 hive_flutter: ^1.1.0 dev_dependencies: hive_generator: ^1.1.5 build_runner: ^2.1.7 - 给Recipe类添加Hive注解:
import 'package:hive/hive.dart'; @HiveType(typeId: 0) // typeId需唯一,自行定义即可 class Recipe { @HiveField(0) final String title; @HiveField(1) final String id; @HiveField(2) final String price; // 其他字段同样添加@HiveField注解,按顺序编号 @HiveField(3) final String url; @HiveField(4) final int servings; @HiveField(5) final String calories; @HiveField(6) final String carbs; @HiveField(7) final String protein; @HiveField(8) final String fat; @HiveField(9) final List<String> ingredients; @HiveField(10) final List<String> instructions; Recipe({ required this.title, required this.id, required this.price, required this.url, required this.servings, required this.calories, required this.carbs, required this.protein, required this.fat, required this.ingredients, required this.instructions, }); } - 运行命令生成适配器:
flutter pub run build_runner build - 在App初始化时注册适配器(比如main函数里):
import 'package:hive/hive.dart'; import 'package:hive_flutter/hive_flutter.dart'; import 'path/to/your/recipe.dart'; void main() async { await Hive.initFlutter(); Hive.registerAdapter(RecipeAdapter()); // 注册生成的适配器 await Hive.openBox('favorites'); runApp(MyApp()); }
- 在
修改存储代码
去掉JSON转换,直接存入Recipe对象:_save() { final recipeData = Recipe( title: widget.recipeDocument['title'], id: widget.recipeDocument['id'], price: widget.recipeDocument['price'], url: widget.recipeDocument['url'], servings: widget.recipeDocument['servings'], calories: widget.recipeDocument['calories'], carbs: widget.recipeDocument['carbs'], protein: widget.recipeDocument['protein'], fat: widget.recipeDocument['fat'], ingredients: widget.recipeDocument['ingredients'], instructions: widget.recipeDocument['instructions'], ); final box = Hive.box('favorites'); final id = widget.recipeDocument['id']; box.put(id, recipeData); // 直接存对象 }修改列表展示代码
直接从box中取出Recipe对象,访问字段:body: ValueListenableBuilder( valueListenable: Hive.box('favorites').listenable(), builder: (context, Box<Recipe> box, child) { List<Recipe> posts = box.values.toList(); return ListView( padding: const EdgeInsets.all(16), children: <Widget>[ const Text('This shows favorites'), ...posts.map( (p) => ListTile( title: Text(p.title), trailing: Text(p.price), ), ), ], ); }, );
方案二:解析取出的JSON字符串(适配现有存储)
如果不想修改存储逻辑,需要把取出的JSON字符串转成Map后再访问字段:
import 'dart:convert'; // 需导入该包 body: ValueListenableBuilder( valueListenable: Hive.box('favorites').listenable(), builder: (context, box, child) { List<String> jsonStrings = box.values.toList().cast<String>(); List<Map<String, dynamic>> posts = jsonStrings.map((str) => jsonDecode(str)).toList(); return ListView( padding: const EdgeInsets.all(16), children: <Widget>[ const Text('This shows favorites'), ...posts.map( (p) => ListTile( title: Text(p['title']), trailing: Text(p['price']), ), ), ], ); }, );
内容的提问来源于stack exchange,提问作者NisiCH
相关产品推荐
相关产品推荐

