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

Flutter中本地存储含Characteristic列表的Product对象的存取问题

解决从SharedPreferences解码包含嵌套Characteristic列表的Product对象问题

看起来你已经在Product类里写好了处理嵌套Characteristic列表的解码逻辑,只是在读取本地存储的时候踩了两个小坑:异步遍历的问题,以及没充分利用已经写好的fromJson工厂方法。下面给你一步步解决:

首先,你需要知道的关键事实

你在Product.fromJson里已经实现了characteristics的解码逻辑——它会遍历JSON里的characteristics数组,逐个调用Characteristic.fromJson生成对象并组装成列表。所以不需要额外写嵌套列表的解码代码,直接用这个工厂方法就行。

修复异步遍历的问题

你原来用forEach配合async回调的方式有问题:forEach不会等待每个异步操作完成,函数会直接走到return products这一步,此时products还是空的。我们可以用两种方式解决:

方式1:用for-in循环(串行获取,逻辑简单)

Future<List<Product>> getProductsFromSharedPrefs() async {
  String productIdsString = await Preference.getValue(key: "ProductIds");
  // 处理空值情况,避免解码报错
  if (productIdsString == null || productIdsString.isEmpty) {
    return [];
  }
  List<dynamic> productIdsList = json.decode(productIdsString);
  List<Product> products = [];

  // 用for-in循环确保等待每个异步读取操作完成
  for (var productId in productIdsList) {
    String productString = await Preference.getValue(key: productId.toString());
    if (productString != null) {
      final decodedProductJson = jsonDecode(productString);
      // 直接调用Product.fromJson,自动处理嵌套的characteristics
      products.add(Product.fromJson(decodedProductJson));
    }
  }

  return products;
}

方式2:用Future.wait(并行获取,效率更高)

如果产品数量较多,并行读取会更快:

Future<List<Product>> getProductsFromSharedPrefs() async {
  String productIdsString = await Preference.getValue(key: "ProductIds");
  if (productIdsString == null || productIdsString.isEmpty) {
    return [];
  }
  List<dynamic> productIdsList = json.decode(productIdsString);

  // 把每个读取+解码操作包装成Future
  List<Future<Product?>> productFutures = productIdsList.map((productId) async {
    String productString = await Preference.getValue(key: productId.toString());
    if (productString == null) return null;
    final decodedProductJson = jsonDecode(productString);
    return Product.fromJson(decodedProductJson);
  }).toList();

  // 等待所有Future完成,过滤掉null值
  List<Product?> results = await Future.wait(productFutures);
  return results.where((product) => product != null).cast<Product>().toList();
}

为什么这样能解决嵌套解码问题?

回顾你写的Product.fromJson:

factory Product.fromJson(Map<String, dynamic> json) {
  var characteristics = new List<Characteristic>();
  json['characteristics'].forEach((v) {
    characteristics.add(Characteristic.fromJson(v));
  });
  return Product(
    id: json['id'],
    price: json['price'].toString(),
    description: json['description'],
    characteristics: characteristics,
  );
}

当你调用Product.fromJson(decodedProductJson)时,它会自动遍历JSON里的characteristics数组,把每个元素转换成Characteristic对象,最终组装成List<Characteristic>赋值给Product的characteristics属性——完全不需要你手动处理嵌套列表的解码!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:31:06