Flutter中DropdownButton绑定Categorie值时出现选项匹配错误如何解决
There should be exactly one item with [DropdownButton]'s value: Instance of 'Categorie'. Either zero or 2 or more [DropdownMenuItem]s were detected with the same value
问题根因
这个报错本质是DropdownButton匹配选中值和下拉选项的value时,匹配结果数量不为1,结合你的代码场景,具体触发原因如下:
- 你使用自定义
Categorie类作为Dropdown的value类型,Dart默认对自定义类实例的相等判断基于内存地址,没有重写==运算符和hashCode的前提下,哪怕两个实例的所有业务属性完全一致,只要是不同的对象实例,就会被判定为不相等。最常见的场景是你给selectedCataId赋值的实例,和cataList中的对应分类实例属性相同但内存地址不同,导致系统找不到匹配的选项,报0个匹配的错误。 - 另外两种常见触发场景:
cataList本身存在重复的分类实例,或者selectedCataId的初始值没有从cataList中选取、是单独创建的实例。
修复方案
你可以选择以下任意一种方案解决问题:
- 方案1:重写Categorie类的相等判断逻辑
根据业务判断两个分类是否相等的核心字段(一般是分类ID)重写==和hashCode,示例代码如下:
class Categorie { final int id; final String label; // 其他属性... Categorie({required this.id, required this.label/*, 其他参数*/}); @override bool operator ==(Object other) => identical(this, other) || other is Categorie && runtimeType == other.runtimeType && id == other.id; // 用核心业务字段判断相等 @override int get hashCode => id.hashCode; }
重写完成后额外做两个检查:
确保
selectedCataId的初始值要么为null,要么是从cataList中取出的实例,不要单独创建同属性的实例赋值检查
cataList数据是否有重复项,可通过cataList = cataList.toSet().toList()去重方案2:改用基础类型作为Dropdown的value
如果不想修改Categorie类的定义,可直接用分类的唯一标识(比如int类型的id)作为Dropdown的value,避免自定义对象的比较问题,修改后的Dropdown代码如下:
// 选中值改为存储分类id,初始值可设为null int? selectedCataId; padding: const EdgeInsets.only(top: 0.0, bottom: 10.0), child: DropdownButton<int>( hint: const Text("Selectionnez une catégorie"), value: selectedCataId, onChanged: (int? newValue) { if(newValue == null) return; setState(() { selectedCataId = newValue; // 从分类列表匹配对应实例赋值 pAudit.categorie = cataList.firstWhere((e) => e.id == newValue); }); }, items: cataList.map((Categorie dropDownCataItem) { return DropdownMenuItem<int>( value: dropDownCataItem.id, child: Text( ' - ${dropDownCataItem.label}', style: const TextStyle(color: Colors.black), ), ); }).toList(), ),
内容的提问来源于stack exchange,提问作者YA TUBE
相关产品推荐
相关产品推荐

