Flutter搜索后已选Recipe的选中视觉标记丢失问题求助
问题:搜索后已选中食谱的勾选标记丢失
- 应用通过API加载食谱并使用
GridView.builder展示,要求用户选择至少3个食谱才能进入后续流程 - 搜索特定食谱后,列表重新加载,已选中食谱的勾选图标(Check icon)丢失,但点击“Continue”按钮后,模态弹窗仍能正常显示所有选中的食谱
- 核心异常:搜索后
if(_selected.contains(recipe))条件不再生效
问题原因
搜索时getRecipes会从API获取新的食谱数据,这些数据是全新的Map实例——即使内容和之前选中的食谱完全一致,它们在内存中的引用地址也不相同。而Dart中List.contains()默认通过引用相等性判断对象是否存在,因此新的recipe对象和_selected列表中的旧对象无法匹配,导致勾选图标无法渲染。
解决方案
方案1:通过唯一ID判断(推荐)
利用食谱的唯一id字段替代对象引用进行判断,这是最简洁可靠的方式:
- 修改所有选中状态的判断逻辑:
// 替换原有的_selected.contains(recipe) _selected.any((item) => item['id'] == recipe['id'])
- 修改点击选中/取消的逻辑:
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:
- 创建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; }
- 修改
getRecipes中的数据转换逻辑:
setState(() { _recipes = response.data['recipes'].map((e) => Recipe.fromMap(e)).toList(); isLoading = false; });
- 后续即可正常使用
_selected.contains(recipe)进行判断。
内容的提问来源于stack exchange,提问作者Martin Skroch
相关产品推荐
相关产品推荐

