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

Flutter中如何将ProductsModel转换为LocalProductsModel存入Hive

解决ProductsModel到LocalProductsModel的转换问题

你遇到的核心问题是:ProductsModel和LocalProductsModel是两个完全独立的Dart类,不能直接用cast强制转换,必须手动实现两者之间的字段映射逻辑。下面是一步步的解决方法:


1. 给Local模型添加转换构造函数

我们需要在每个Local模型中添加一个从对应原模型转换的构造方法,把原模型的字段值逐个映射到Local模型中。

1.1 给LocalCategoriesModel添加转换构造

class LocalCategoriesModel {
  // 保留原有代码...
  
  // 添加从CategoriesModel转换的构造
  factory LocalCategoriesModel.fromCategoriesModel(CategoriesModel model) {
    return LocalCategoriesModel(
      id: model.id,
      name: model.name,
    );
  }
}

1.2 给LocalImagesModel添加转换构造

class LocalImagesModel{
  // 保留原有代码...
  
  // 添加从ImagesModel转换的构造
  factory LocalImagesModel.fromImagesModel(ImagesModel model) {
    return LocalImagesModel(
      id: model.id,
      src: model.src,
      name: model.name,
    );
  }
}

1.3 给LocalProductsModel添加转换构造

这个构造需要处理列表类型的字段(categories和images),逐个转换列表中的元素:

@HiveType(typeId: 0)
class LocalProductsModel {
  // 保留原有代码...
  
  // 添加从ProductsModel转换的构造
  factory LocalProductsModel.fromProductsModel(ProductsModel model) {
    // 转换分类列表:把每个CategoriesModel转成LocalCategoriesModel
    final localCategories = model.categories?.map((cat) => LocalCategoriesModel.fromCategoriesModel(cat))?.toList() ?? [];
    // 转换图片列表:把每个ImagesModel转成LocalImagesModel
    final localImages = model.images?.map((img) => LocalImagesModel.fromImagesModel(img))?.toList() ?? [];
    
    return LocalProductsModel(
      id: model.id,
      name: model.name,
      catalog_visibility: model.catalog_visibility,
      description: model.description,
      short_description: model.short_description,
      price: model.price,
      regular_price: model.regular_price,
      sale_price: model.sale_price,
      date_created: model.date_created,
      categories: localCategories,
      images: localImages,
    );
  }
}

2. 修复Hive存储逻辑

你之前存的是ProductsModel转成的Map,现在我们直接转换为LocalProductsModel实例再存入Hive(Hive会自动处理序列化):

postCartLocal(ProductsModel products){
  // 先把ProductsModel转换为LocalProductsModel
  final localProduct = LocalProductsModel.fromProductsModel(products);
  // 直接存入Hive,无需手动转Map
  Hive.box('cart').add(localProduct);
}

3. 修复Hive读取逻辑

现在Hive中存储的是LocalProductsModel实例,读取时可以直接获取,不需要错误的类型转换:

Widget _buildListView(){
  return ValueListenableBuilder(
    valueListenable: Hive.box('cart').listenable(),
    builder: (context, Box cartBox, widget){
      return ListView.builder(
        itemCount: cartBox.length,
        itemBuilder: (context, index) {
          // 直接获取LocalProductsModel实例
          final cartItem = cartBox.getAt(index) as LocalProductsModel;
          print('商品名称:${cartItem.name}');
          // 记得返回实际的列表项Widget,比如ListTile
          return ListTile(
            title: Text(cartItem.name),
            subtitle: Text(cartItem.price ?? cartItem.regular_price),
          );
        },
      );
    },
  );
}

4. 确保Hive序列化适配器正确生成

因为你的Local模型使用了Hive的注解(@HiveType、@HiveField),需要确保已经生成了对应的适配器:

  1. 执行命令生成适配器:
flutter packages pub run build_runner build
  1. 在App初始化时注册所有适配器:
void main() async {
  await Hive.initFlutter();
  // 注册所有Local模型的适配器
  Hive.registerAdapter(LocalProductsModelAdapter());
  Hive.registerAdapter(LocalCategoriesModelAdapter());
  Hive.registerAdapter(LocalImagesModelAdapter());
  // 打开Hive盒子(如果还没打开)
  await Hive.openBox('cart');
  
  runApp(MyApp());
}

注意:如果你的LocalCategoriesModel和LocalImagesModel之前没有添加@HiveType和@HiveField注解,需要补上(参考下面的示例),否则Hive无法序列化这两个类型:

@HiveType(typeId: 1) // typeId要唯一,不能和其他模型重复
class LocalCategoriesModel {
  @HiveField(0)
  final int id;
  @HiveField(1)
  final String name;
  
  // 保留原有构造和方法...
}

@HiveType(typeId: 2)
class LocalImagesModel{
  @HiveField(0)
  final int id;
  @HiveField(1)
  final String src;
  @HiveField(2)
  final String name;
  
  // 保留原有构造和方法...
}

这样修改后,就能顺利完成ProductsModel到LocalProductsModel的转换,并且正常存入和读取Hive本地存储了。

内容的提问来源于stack exchange,提问作者aJaysanity

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.08 12:37:28