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

Flutter中FutureBuilder加载SharedPreferences数据给DropDownButton赋值报错问题

问题根因

这个报错是Flutter DropdownButton的强制校验规则触发:要求绑定的value必须在items的value集合中存在且唯一,触发场景有两种:

  1. 当前绑定的dropdownValue不在异步加载回来的下拉选项值列表中
  2. 下拉选项值列表存在重复值

解决步骤

  1. 校验下拉值合法性
    异步拿到下拉列表后先做合法性校验,如果当前dropdownValue不在列表中,自动重置为列表第一个值,避免匹配失败。
  2. 避免Future重复执行
    不要把getDropDownItems()直接写在FutureBuilder的future参数中,每次组件刷新都会生成新的Future实例导致状态异常,建议在initState中提前初始化Future变量。
  3. 列表去重
    生成下拉选项前先对列表去重,避免重复值导致匹配到多个结果。
  4. 索引取值适配
    选择下拉选项后不要用全局的konzernDataTitle找索引,要以实际加载的当前列表为准,避免本地存储的列表和全局列表内容不一致导致索引错位。

代码修改示例

1. 状态变量与初始化

class _YourPageState extends State<YourPage> {
  late Future<List<DropdownMenuItem<String>>> _dropDownItemsFuture;
  String? dropdownValue;
  // 其余原有变量保持不变

  @override
  void initState() {
    super.initState();
    _dropDownItemsFuture = getDropDownItems();
  }
  // 其余原有代码
}

2. 优化getDropDownItems方法

Future<List<DropdownMenuItem<String>>> getDropDownItems() async {
  SharedPreferences prefs = await SharedPreferences.getInstance();
  List<String> actualList;
  if (prefs.containsKey("prefsKonzernTitle")) {
    actualList = prefs.getStringList("prefsKonzernTitle") ?? konzernDataTitle;
  } else {
    actualList = konzernDataTitle;
  }
  // 列表去重
  final uniqueList = actualList.toSet().toList();
  return uniqueList.map((data) {
    return DropdownMenuItem<String>(
      value: data,
      child: Text(data),
    );
  }).toList();
}

3. 优化FutureBuilder组件

FutureBuilder<List<DropdownMenuItem<String>>>(
  future: _dropDownItemsFuture,
  builder: (context, snapshot) {
    if (!snapshot.hasData) {
      return const SizedBox();
    }
    final items = snapshot.data!;
    final valueList = items.map((e) => e.value).toList();
    // 校验值合法性
    if (dropdownValue == null || !valueList.contains(dropdownValue)) {
      dropdownValue = valueList.first;
    }
    return DropdownButton<String>(
      value: dropdownValue,
      items: items,
      onChanged: (String? newValue) {
        if (newValue == null) return;
        setState(() {
          dropdownValue = newValue;
          int index = valueList.indexOf(newValue);
          // 如果关联的link、image等数据也存在本地,需要先取出本地存储的对应列表再取值
          titleController.text = valueList[index];
        });
      },
    );
  }
)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 15:57:04