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

Flutter搜索后已选Recipe的选中视觉标记丢失问题求助

问题:搜索后已选中食谱的勾选标记丢失
  • 应用通过API加载食谱并使用GridView.builder展示,要求用户选择至少3个食谱才能进入后续流程
  • 搜索特定食谱后,列表重新加载,已选中食谱的勾选图标(Check icon)丢失,但点击“Continue”按钮后,模态弹窗仍能正常显示所有选中的食谱
  • 核心异常:搜索后if(_selected.contains(recipe))条件不再生效

问题原因

搜索时getRecipes会从API获取新的食谱数据,这些数据是全新的Map实例——即使内容和之前选中的食谱完全一致,它们在内存中的引用地址也不相同。而Dart中List.contains()默认通过引用相等性判断对象是否存在,因此新的recipe对象和_selected列表中的旧对象无法匹配,导致勾选图标无法渲染。

解决方案

方案1:通过唯一ID判断(推荐)

利用食谱的唯一id字段替代对象引用进行判断,这是最简洁可靠的方式:

  1. 修改所有选中状态的判断逻辑:
// 替换原有的_selected.contains(recipe)
_selected.any((item) => item['id'] == recipe['id'])
  1. 修改点击选中/取消的逻辑:
onTap: () {
  setState(() {
    final isSelected = _selected.any((item) => item['id'] == recipe['id']);
    if (isSelected) {
      _selected.removeWhere((item) => item['id'] == recipe['id']);
    } else {
      _selected.add(recipe);
    }
  });
},

方案2:自定义Recipe类并重写相等性判断

如果需要更规范的数据模型,可以创建自定义Recipe类,重写==运算符和hashCode,让相等性判断基于唯一id:

  1. 创建Recipe模型类:
class Recipe {
  final int id;
  final String name;
  final String image;

  Recipe({required this.id, required this.name, required this.image});

  factory Recipe.fromMap(Map<String, dynamic> map) {
    return Recipe(
      id: map['id'],
      name: map['name'],
      image: map['image'],
    );
  }

  @override
  bool operator ==(Object other) =>
      identical(this, other) ||
      other is Recipe && runtimeType == other.runtimeType && id == other.id;

  @override
  int get hashCode => id.hashCode;
}
  1. 修改getRecipes中的数据转换逻辑:
setState(() {
  _recipes = response.data['recipes'].map((e) => Recipe.fromMap(e)).toList();
  isLoading = false;
});
  1. 后续即可正常使用_selected.contains(recipe)进行判断。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 03:05:00