DropdownButton2重复value断言错误求助(GetX+DropdownButtonHideUnderline)
使用DropdownButtonHideUnderline组件,通过GetX管理状态时,触发DropdownButton2断言错误,提示「检测到0个或2个及以上拥有相同value的DropdownMenuItem」,怀疑问题出在DropdownButton2的value属性上,寻求解决方法。
组件代码
DropdownButtonHideUnderline( child: Obx( () => DropdownButton2( isExpanded: true, hint: Row( children: const [ Icon( Icons.list, size: 16, color: Colors.yellow, ), SizedBox( width: 4, ), Expanded( child: Text( 'Add to', style: TextStyle( fontSize: 14, fontWeight: FontWeight.bold, color: Colors.yellow, ), overflow: TextOverflow.ellipsis, ), ), ], ), items: homeCtrl.tasks.map( (element) { final color = HexColor(element.color); return DropdownMenuItem<TaskTest>( value: element, child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Row( children: [ Icon( IconData(element.icon, fontFamily: 'MaterialIcons'), color: color, ), SizedBox( width: 10, ), Text( element.title, overflow: TextOverflow.ellipsis, ), ], ), if (homeCtrl.selectedValue.value == element) FaIcon(FontAwesomeIcons.circleCheck, color: customColor.kBlue), ], ), ); }, ).toList(), value: homeCtrl.selectedValue.value, onChanged: (value) => homeCtrl.setDropDownValue(value as TaskTest), icon: const Icon( Icons.arrow_forward_ios_outlined, ), iconSize: 14, iconEnabledColor: Colors.yellow, iconDisabledColor: Colors.grey, buttonHeight: 35, buttonWidth: double.infinity, buttonPadding: const EdgeInsets.only(left: 14, right: 14), buttonDecoration: BoxDecoration( gradient: kPinkGradient, borderRadius: BorderRadius.circular(14), border: Border.all( color: Colors.black26, ), color: Colors.deepPurpleAccent, ), buttonElevation: 2, itemHeight: 30, itemPadding: const EdgeInsets.only(left: 14, right: 14), dropdownMaxHeight: 200, dropdownWidth: 200, dropdownPadding: null, dropdownDecoration: BoxDecoration( gradient: kPinkGradient, borderRadius: BorderRadius.circular(14), color: Colors.deepPurpleAccent, ), dropdownElevation: 8, scrollbarRadius: const Radius.circular(40), scrollbarThickness: 6, scrollbarAlwaysShow: true, offset: const Offset(-20, 0), ), ), ),
HomeController 相关代码
状态变量
final selectedValue = Rx<TaskTest?>(null);
下拉选项切换方法
void setDropDownValue(TaskTest? newValue) { selectedValue.value = newValue; }
错误信息
======== Exception caught by widgets library ======================================================= The following assertion was thrown building Obx(has builder, dirty, state: _ObxState#78790): There should be exactly one item with [DropdownButton]'s value: TaskTest(health, 59737, #FFfa63c6). Either zero or 2 or more [DropdownMenuItem]s were detected with the same value 'package:dropdown_button2/dropdown_button2.dart': Failed assertion: line 968 pos 11: 'items == null || items.isEmpty || value == null || items.where((DropdownMenuItem<T> item) { return item.value == value; }).length == 1' The relevant error-causing widget was: Obx Obx:file:///E:/flutter-projects-licotab/bootcamp/task_managment_test/lib/widgets/task_sheet.dart:494:30 When the exception was thrown, this was the stack: #2 new DropdownButton2 (package:dropdown_button2/dropdown_button2.dart:968:11)
解决方案
核心原因
DropdownButton2要求选中的value必须在items列表中存在且唯一,触发错误的常见场景:
TaskTest类未重写==运算符和hashCode,导致对象按引用而非内容比较,出现"明明相同却不匹配"或"重复项被判定为不同"的矛盾。selectedValue的value不在当前homeCtrl.tasks列表中(比如列表更新后选中项被移除)。homeCtrl.tasks中存在多个内容完全一致的TaskTest对象,导致匹配到多个项。
具体修复步骤
1. 给TaskTest类重写==和hashCode
因为用TaskTest对象作为value,默认的引用比较无法满足业务逻辑,必须按内容比较:
class TaskTest { final String title; final int icon; final String color; TaskTest(this.title, this.icon, this.color); @override bool operator ==(Object other) { if (identical(this, other)) return true; return other is TaskTest && other.title == title && other.icon == icon && other.color == color; } @override int get hashCode => Object.hash(title, icon, color); }
2. 确保选中值始终在列表中
如果tasks列表动态更新,需在更新后校验选中项是否存在,不存在则重置:
// HomeController中更新tasks的示例方法 void updateTasks(List<TaskTest> newTasks) { tasks.value = newTasks; if (!tasks.value.contains(selectedValue.value)) { selectedValue.value = null; } }
3. 确保tasks列表无重复项
检查homeCtrl.tasks是否存在重复的TaskTest对象,可通过去重处理:
// 方式1:利用Set去重(前提是已重写==和hashCode) List<TaskTest> uniqueTasks = homeCtrl.tasks.toSet().toList(); // 方式2:自定义去重逻辑 List<TaskTest> uniqueTasks = []; for (var task in homeCtrl.tasks) { if (!uniqueTasks.any((t) => t == task)) { uniqueTasks.add(task); } }
4. 调试排查(可选)
若仍未定位问题,可添加调试代码查看匹配数量:
// 在生成items后添加调试代码 final items = homeCtrl.tasks.map(...).toList(); final matchCount = items.where((item) => item.value == homeCtrl.selectedValue.value).length; print("匹配到的项数量:$matchCount");
内容的提问来源于stack exchange,提问作者peyman bozorgnezhad
相关产品推荐
相关产品推荐

