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

Flutter中DropdownButton默认值设置失败,运行时报错求助

Flutter GetX中DropdownButtonFormField断言错误与默认值初始化问题

我在Flutter项目中使用GetX框架实现DropdownButtonFormField时,编译阶段无报错,但运行时触发如下断言错误:

'Package:flutter/src/material/dropdown.dart':Failed assertion : line 1606 pos 15: items==null || items.isEmpty || value==null || items.where ((DropdownMenuItem <T> item){
return item.value == value;}).length == 1': There should be exactly one item with [DropdownButton]'s value:. Either zero or 2 or more [DropdownButton]'s were detected with the same value.

自定义Dropdown组件代码

import 'package:flutter/material.dart';
import 'package:get/get.dart';

class MyStatesDropdown extends StatelessWidget {
  final String value;
  final Function(String newValue) onChanged;
  final List<Map<String, String>> items;

  MyStatesDropdown(
      {super.key,
      required this.value,
      required this.onChanged,
      required this.items});

  @override
  Widget build(BuildContext context) {
    return Obx(() => Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Center(
                child: DropdownButtonFormField(
              decoration: InputDecoration(
                  isDense: true,
                  border: OutlineInputBorder(
                      borderRadius: BorderRadius.circular(5.0)),
                  focusedBorder: OutlineInputBorder(
                      borderRadius: BorderRadius.circular(5.0)),
                  hintText: 'Select State',
                  hintStyle: TextStyle(color: Colors.grey.shade800)),
              value: value,
              onChanged: (newVal) => onChanged(newVal ?? ''),
              items: items.map((Map item) {
                return DropdownMenuItem<String>(
                    value: item['scode'], child: Text(item['sname']));
              }).toList(),
              icon: Icon(Icons.arrow_drop_down),
              iconSize: 42,
            )),
          ],
        ));
  }
}

GetX控制器代码

.................
  final istates = [
    {'scode': '35', 'sname': 'Andaman & Nicobar Islands'},
    {'scode': '37', 'sname': 'Andhra Pradesh'},
    {'scode': '12', 'sname': 'Arunachal Pradesh'},
    {'scode': '18', 'sname': 'Assam'},
    {'scode': '10', 'sname': 'Bihar'},
    {'scode': '04', 'sname': 'Chandigarh'},
    {'scode': '22', 'sname': 'Chattisgarh'},
    {'scode': '26', 'sname': 'Dadra & Nagar Haveli & Daman & Diu'},
    {'scode': '07', 'sname': 'Delhi'},
    {'scode': '30', 'sname': 'Goa'},
    {'scode': '24', 'sname': 'Gujarat'},
    {'scode': '06', 'sname': 'Haryana'},
    {'scode': '02', 'sname': 'Himachal Pradesh'},
    {'scode': '01', 'sname': 'Jammu & Kashmir'},
    {'scode': '20', 'sname': 'Jharkhand'},
    {'scode': '29', 'sname': 'Karnataka'},
    {'scode': '32', 'sname': 'Kerala'},
    {'scode': '38', 'sname': 'Ladakh'},
    {'scode': '31', 'sname': 'Lakshwadeep'},
    {'scode': '23', 'sname': 'Madhya Pradesh'},
    {'scode': '27', 'sname': 'Maharashtra'},
    {'scode': '14', 'sname': 'Manipur'},
    {'scode': '17', 'sname': 'Meghalaya'},
    {'scode': '15', 'sname': 'Mizoram'},
    {'scode': '13', 'sname': 'Nagaland'},
    {'scode': '21', 'sname': 'Odisha'},
    {'scode': '34', 'sname': 'Puducherry'},
    {'scode': '03', 'sname': 'Punjab'},
    {'scode': '08', 'sname': 'Rajasthan'},
    {'scode': '11', 'sname': 'Sikkim'},
    {'scode': '33', 'sname': 'Tamil Nadu'},
    {'scode': '36', 'sname': 'Telangana'},
    {'scode': '16', 'sname': 'Tripura'},
    {'scode': '09', 'sname': 'Uttar Pradesh'},
    {'scode': '15', 'sname': 'Uttrakhand'},
    {'scode': '19', 'sname': 'West Bengal'}
  ];

  var selectedStateSA = ''.obs;

  void updtSelectedStateSA(String val) {
    selectedStateSA.value = val;
  }

...............

页面调用组件代码

...........
MyStatesDropdown(
    value:
        _genContllr.selectedStateSA.value,
    onChanged: (newValue) => _genContllr
        .updtSelectedStateSA(newValue),
    items: _genContllr.istates),

...........

问题原因及修复方案

1. 数据源重复值问题

你的istates列表中,Mizoram和Uttrakhand的scode均为'15',导致DropdownButton匹配到两个相同值,触发断言错误。需修改重复的scode为唯一值,例如:

{'scode': '05', 'sname': 'Uttrakhand'},

2. 默认值初始化问题

当前默认值为空字符串'',但数据源中无对应选项,同样会触发断言。有两种处理方式:

  • 方式一:设置有效默认值
    将selectedStateSA初始化为数据源中存在的scode,比如:
var selectedStateSA = '35'.obs; // 对应Andaman & Nicobar Islands
  • 方式二:允许空初始状态(显示hint)
    若需默认显示提示文本、不选中任何选项,需修改以下内容:
    • 控制器中修改变量类型为可空字符串:
      var selectedStateSA = RxString?();
      
    • 自定义组件更新参数类型及Dropdown配置:
      class MyStatesDropdown extends StatelessWidget {
        final String? value; // 改为可空类型
        final Function(String newValue) onChanged;
        final List<Map<String, String>> items;
      
        MyStatesDropdown(
            {super.key,
            required this.value,
            required this.onChanged,
            required this.items});
      
        @override
        Widget build(BuildContext context) {
          return Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Center(
                  child: Obx(() => DropdownButtonFormField<String>(
                        decoration: InputDecoration(
                            isDense: true,
                            border: OutlineInputBorder(
                                borderRadius: BorderRadius.circular(5.0)),
                            focusedBorder: OutlineInputBorder(
                                borderRadius: BorderRadius.circular(5.0)),
                            hintText: 'Select State',
                            hintStyle: TextStyle(color: Colors.grey.shade800)),
                        value: value,
                        onChanged: (newVal) {
                          if (newVal != null) onChanged(newVal);
                        },
                        items: items.map((Map item) {
                          return DropdownMenuItem<String>(
                              value: item['scode'], child: Text(item['sname']));
                        }).toList(),
                        icon: Icon(Icons.arrow_drop_down),
                        iconSize: 42,
                      ))),
            ],
          );
        }
      }
      

3. 组件优化建议

将Obx的包裹范围缩小至DropdownButtonFormField,避免不必要的UI重建:

@override
Widget build(BuildContext context) {
  return Column(
    mainAxisAlignment: MainAxisAlignment.center,
    children: [
      Center(
          child: Obx(() => DropdownButtonFormField<String>(
                // 原有配置不变
              ))),
    ],
  );
}

内容的提问来源于stack exchange,提问作者gomesh munda

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.30 12:25:55