Flutter如何在setState()中调用方法?触发DropdownButton报错如何解决?
问题原因
- 你将下拉组件所在的
customers容器定义为了final常量,常量仅会在初始化时构建一次,后续调用setState更新状态后,该组件不会跟着重新渲染,导致下拉的选中值和可选项不匹配。 - 选中值
_customerSelection的类型和DropdownMenuItem返回的value类型不匹配:你在构造DropdownMenuItem时将CustomerID转成了字符串类型,如果_customerSelection定义为int类型,就会出现3 != "3"的匹配失败问题,找不到对应value的item。 - 异步方法调用逻辑错误:
getProductData是异步方法,直接放在setState的同步执行块内不会等待接口返回,且状态更新逻辑拆分错误。 - 没有做可选值合法性校验:初始
_customerSelection或者切换后的选中值,可能不在当前customerData的CustomerID列表内,或者customerData存在重复ID的项,触发了Dropdown的内置校验报错。
解决方案
- 把常量形式的组件改成动态构建的方法,确保每次
setState都会重新渲染下拉组件:
// 移除原来的final customers = ... 的定义,改成如下方法 Widget _buildCustomers() { return Container( child: Row( children: [ Row( children: <Widget>[ Container( padding: EdgeInsets.only(left:5), child: Text('Customer :') ) ], ), Row( children: <Widget>[Container( padding: EdgeInsets.only(left:5), child: DropdownButton( value: _customerSelection, items: customerData.map((product) { return DropdownMenuItem( value: product["CustomerID"].toString(), child: Text(product["CustomerName"]!) ); }).toList(), onChanged: (String? newValue) { if (newValue == null) return; // 先更新选中值刷新下拉状态 setState(() { _customerSelection = newValue; }); // 单独调用异步拉取产品数据的方法 getProductData(); }, hint: Text('Customer'), ) ), ], ) ], ), ); } // 在build方法中调用该方法渲染组件,不要直接用之前的final变量
- 统一选中值类型:将
_customerSelection的类型定义为String?,初始值如果是数字的话也要转成字符串,比如初始值为3的话要写成String? _customerSelection = "3"; - 增加合法值校验,在拉取客户数据的地方做兜底处理,避免选中值不在可选列表内:
// 你在initState拉取customerData的逻辑中补充校验 setState(() { customerData = 接口返回的客户列表; // 新增校验逻辑 if (customerData.isNotEmpty) { final validIdList = customerData.map((e) => e["CustomerID"].toString()).toList(); // 如果当前选中值为空或者不在合法列表内,默认选中第一个 if (_customerSelection == null || !validIdList.contains(_customerSelection)) { _customerSelection = validIdList.first; } } });
- 检查后端返回的客户列表数据,确保所有
CustomerID唯一没有重复,如果有重复数据要先做去重处理再赋值给customerData。
内容的提问来源于stack exchange,提问作者Malone
相关产品推荐
相关产品推荐

