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

Flutter二级DropdownButton切换时出现重复值错误求助

问题分析

错误提示there should be exactly one item with dropdownbutton 's value either zero or 2 or more [DropdownMenuItem]s were detected with the same value的核心原因:

  • 切换第一个下拉菜单(Gol)时,第二个下拉菜单(Vehicle)的选中值vehicleValue未被重置,仍保留旧值。
  • 新切换后的车辆列表中不存在该旧值,导致DropdownButtonFormField无法匹配到对应的DropdownMenuItem,触发异常。
  • 第二个下拉菜单未绑定value参数,控件无法正确关联选中状态。
解决方案

1. 重置第二个下拉的选中值

在第一个下拉的onChanged回调中,更新golValue后立即将vehicleValue设为null,确保新车辆列表加载时,下拉菜单处于未选中状态。

2. 绑定第二个下拉的value参数

调用_buildDropdown时,给第二个下拉传入value: Data.vehicleValue,让控件正确关联选中值。

修改后的代码

main.dart

import 'package:flutter/material.dart';
import 'package:perhitungan_pkt_kgb/data.dart';

class HitungPkt extends StatefulWidget {
  const HitungPkt({super.key});

  @override
  State<HitungPkt> createState() => _HitungPktState();
}

class _HitungPktState extends State<HitungPkt> {
  @override
  Widget build(BuildContext context) {
    return Form(
      child: Column(
        children: [
          _buildDropdown(
              label: 'Gol',
              items: Data.gol.cast<Map<String, dynamic>>(),
              value: Data.golValue,
              onChanged: (String? newValue) {
                setState(() {
                  Data.golValue = newValue;
                  Data.vehicleValue = null; // 重置第二个下拉的选中值
                  Data.vehicle = Data.cekgol();
                });
              }),

          if (Data.vehicle != null && Data.vehicle!.isNotEmpty)
            _buildDropdown(
                label: 'Vehicle',
                items: Data.vehicle!.cast<Map<String, dynamic>>(),
                value: Data.vehicleValue, // 绑定第二个下拉的选中值
                onChanged: (String? newValue) {
                  setState(() {
                    Data.vehicleValue = newValue;
                  });
                }),
        ],
      ),
    );
  }

  Widget _buildDropdown({
    required String label,
    required List<Map<String, dynamic>> items,
    required void Function(String?) onChanged,
    String? value,
  }) {
    return DropdownButtonFormField<String>(
        decoration: InputDecoration(
          labelText: label,
          hintStyle: const TextStyle(color: Colors.blue),
          border: OutlineInputBorder(
            borderRadius: BorderRadius.circular(10),
            borderSide: const BorderSide(color: Colors.blue),
          ),
          focusedBorder: OutlineInputBorder(
            borderSide: const BorderSide(color: Colors.blue),
            borderRadius: BorderRadius.circular(10),
          ),
          enabledBorder: OutlineInputBorder(
            borderSide: const BorderSide(color: Colors.blue),
            borderRadius: BorderRadius.circular(10),
          ),
          errorBorder: OutlineInputBorder(
            borderSide: const BorderSide(color: Colors.blue),
            borderRadius: BorderRadius.circular(10),
          ),
        ),
        value: value,
        items: items.map((item) {
          return DropdownMenuItem<String>(
            value: item['value'] as String,
            child: Text(item['label'] as String),
          );
        }).toList(),
        onChanged: onChanged);
  }
}

data.dart

class Data{
  static const List gol = [
    {'value': 'Car', 'label': 'Car'},
    {'value': 'Bus', 'label': 'Bus'},
    {'value': 'Plane', 'label': 'Plane'}
  ];
  static String? golValue;
  static String? vehicleValue;
  static List? vehicle;
  
  static List cekgol() {
    if (golValue == 'Car') {
      return [
        {'value': 'car1', 'label': 'car1'},
        {'value': 'car2', 'label': 'car2'},
        {'value': 'car3', 'label': 'car3'},
        {'value': 'car4', 'label': 'car4'},
        {'value': 'car5', 'label': 'car5'}
      ];
    } else if (golValue == 'Bus') {
      return [
        {'value': 'Bus1', 'label': 'Bus1'},
        {'value': 'Bus2', 'label': 'Bus2'},
        {'value': 'Bus3', 'label': 'Bus3'},
        {'value': 'Bus4', 'label': 'Bus4'}
      ];
    } else if (golValue == 'Plane') {
      return [
        {'value': 'Plane1', 'label': 'Plane1'},
        {'value': 'Plane2', 'label': 'Plane2'},
        {'value': 'Plane3', 'label': 'Plane3'},
        {'value': 'Plane4', 'label': 'Plane4'},
        {'value': 'Plane5', 'label': 'Plane5'}
      ];
    } else {
      return [];
    }
  }
}

额外优化建议

  • 尽量避免使用全局静态变量管理状态,小型项目可用StatefulWidget成员变量替代,大型项目推荐Provider、Riverpod等状态管理方案,减少全局状态副作用。
  • 对Data.vehicle的非空判断更严谨,避免空列表时显示第二个下拉菜单。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 09:27:05