Flutter DropdownButton选中值不显示,报DropdownMenuItem同值数量异常问题
问题原因
这个报错触发的核心逻辑是Flutter要求DropdownButton绑定的value值,在给定的DropdownMenuItem列表中必须唯一存在,要么0个要么多个都会触发断言失败,你的代码存在以下几个明确问题:
courseItems为外部变量,每次StreamBuilder刷新触发重绘时,你都会重复向列表中添加选项,导致相同value的item重复出现- 空判断顺序错误:在遍历完snapshot数据之后才判断数据是否为空,为空时遍历逻辑已经执行会抛出越界错误
- 循环长度写死为2:如果Firebase返回的课程数量不足2条,直接取下标
i=0/1会触发数组越界 - 未校验
selected初始值:如果selected初始赋值不在最终生成的courseItems的value集合中,也会触发该错误
修复步骤
- 调整判空顺序,先判断数据合法性再执行遍历逻辑
- 每次生成下拉选项前清空
courseItems,或者直接在builder内部创建临时选项列表,避免重复累加 - 循环长度使用返回数据的实际长度,避免越界,如果你确实只需要最多2条,可以取
min(2, listViewCourseRecordList.length)作为循环上限 - 校验
selected值,如果初始值不在选项列表中,将其重置为null或者第一个选项的value
修复后代码示例
import 'dart:math'; // 用到min函数需要导入该包 return StreamBuilder<List<CoursesRecord>>( stream: queryCourseRecord( queryBuilder: (courseRecord) => courseRecord.orderBy('${widget.orderBy}', descending: true), limit: 5, ), builder: (context, snapshot) { // 加载态处理 if (!snapshot.hasData) { return Center( child: SizedBox( width: 50, height: 50, child: CircularProgressIndicator( color: FlutterFlowTheme.primaryColor, ), ), ); } List<CoursesRecord> listViewCourseRecordList = snapshot.data; // 优先处理空数据情况 if (listViewCourseRecordList.isEmpty) { return Container( height: 100, child: Center( child: Text('No results.'), ), ); } // 每次重新生成选项列表,避免重复累加 List<DropdownMenuItem> courseItems = []; // 用实际数据长度作为上限,最多取2条 int itemCount = min(2, listViewCourseRecordList.length); for (int i = 0; i < itemCount; i++) { String value = listViewCourseRecordList[i].name; courseItems.add( DropdownMenuItem( child: Container( width: 316, child: CourseBoxName(coursesRecord: listViewCourseRecordList[i],)), value: value, ), ); } // 校验selected值是否在选项中,不在则重置为null List valueList = courseItems.map((e) => e.value).toList(); if(selected != null && !valueList.contains(selected)){ selected = null; } return Container( width: MediaQuery.of(context).size.width, height: 100, child: DropdownButtonHideUnderline( child: ButtonTheme( alignedDropdown: true, child: DropdownButton( value: selected, isDense: true, items: courseItems, hint: Text( "Выберите курс", ), onChanged: (newValue) { setState(() { selected = newValue; widget.courseSelected(newValue); }); }, isExpanded: false, ), ), ), ); }, );
额外注意事项
- 如果你的课程存在重名情况,不要用课程名称作为value,可以改用Firebase文档ID等唯一标识作为
DropdownMenuItem的value,避免重复 - 如果使用null作为初始值,要确保Dart SDK版本开启了空安全适配,或者显式声明
DropdownButton的泛型为可空类型
内容的提问来源于stack exchange,提问作者Amiden
相关产品推荐
相关产品推荐

