Flutter中使用API返回的JSON列表实现客户选择下拉框
问题根源
你现在代码跑不通的核心原因有三个:
- 类型用错了:
CustomerIDs解析完成后是List<CustomerJson>类型的自定义类对象列表,不是Map结构,写value["customer"]根本访问不到属性,Dart里自定义类要直接用.属性名访问字段 - 空状态没处理:页面刚加载的时候API还没返回数据,
CustomerIDs还没赋值,直接写CustomerIDs[0]会直接抛未初始化/越界错误 - 选中值类型不匹配:你把
CustomerID_value声明成String?,但给下拉项传的value是整个CustomerJson对象,类型对不上会导致选中后不显示、初始值报错。
修复方案
1. 先修正变量声明
把状态类里的两个变量声明改掉,不要用dynamic/var糊类型,明确类型避免运行时报错:
// 替换原来的 late var CustomerIDs; late List<CustomerJson> CustomerIDs = []; // 初始给空数组,避免未初始化问题 // 替换原来的 String? CustomerID_value; 存整个客户对象,后续取其他客户字段更方便 CustomerJson? CustomerID_value;
2. 页面初始化时加载客户数据
在状态类的initState生命周期里触发API请求,拿到数据后再刷新UI:
@override void initState() { super.initState(); _loadCustomerData(); } Future<void> _loadCustomerData() async { // 替换成你实际的APIKey值 final customerList = await GetCustomerIDsCall("你的APIKey"); if (customerList.isNotEmpty && mounted) { setState(() { CustomerIDs = customerList; // 需要默认选中第一个客户就留这行,不需要就删掉 CustomerID_value = customerList.first; }); } }
3. 改下拉组件代码
把原来的DropdownButton部分替换成下面的,加加载态判断,属性访问改成类属性访问:
Center( child: Container( width: 200, padding: const EdgeInsets.symmetric(vertical: 16), child: DropdownButtonHideUnderline( // 数据没加载完显示加载圈 child: CustomerIDs.isEmpty ? const SizedBox( width: 20, height: 20, child: CircularProgressIndicator(strokeWidth: 2), ) : DropdownButton<CustomerJson>( value: CustomerID_value, hint: const Text('Customer ID'), items: CustomerIDs.map((customerItem) { return DropdownMenuItem<CustomerJson>( value: customerItem, // customer是可空字段,加空兜底避免显示null child: Text(customerItem.customer ?? '未知客户'), ); }).toList(), onChanged: (selected) { setState(() { CustomerID_value = selected; // 如果需要把客户ID同步到表单控制器,加这行 customerIDController.text = selected?.customer ?? ''; }); }, ), ), ), ),
4. 补全API方法的异常兜底
你原来的API方法请求失败的时候没有返回值,会触发类型错误,改成下面的:
Future<List<CustomerJson>> GetCustomerIDsCall(String APIKey) async { var headers = {'APIKey': APIKey}; var request = http.Request( 'GET', Uri.parse('http://65.254.144.50:5114/Customers') ); request.headers.addAll(headers); try { final response = await request.send(); final String respStr = await response.stream.bytesToString(); if (response.statusCode == 200) { final responseList = json.decode(respStr) as List; return responseList.map((item) => CustomerJson.fromJson(item)).toList(); } else { print(response.reasonPhrase); return []; } } catch (e) { print('拉取客户列表异常: $e'); return []; } }
可选调整
如果你不需要存整个客户对象,只需要存选中的客户ID字符串,把DropdownButton的泛型改成String,下拉项的value传customerItem.customer,CustomerID_value改回String?类型就行,后续提交表单直接取这个值即可。
内容的提问来源于stack exchange,提问作者Aiden P
相关产品推荐
相关产品推荐

