Flutter使用Provider实现API数据下拉列表时按钮禁用问题排查
核心错误点
- 数据更新未通知UI:
fetchBlood方法中,notifyListeners()被放在了if(response.statusCode ==200)分支外部,且分支内存在return语句,导致成功获取数据后不会触发UI更新通知,bloodList始终为空,Dropdown因无可用选项被禁用。 - Provider实例不统一:
Homepage的initState中自行实例化了BloodProvider,但UI通过Provider.of获取的是全局注册的实例,两者数据不共享,API请求的结果无法同步到UI监听的实例中。
修正后的Provider代码
import 'dart:convert'; import 'package:flutter/cupertino.dart'; import '../model/blood_groups.dart'; import '../util/api_url.dart'; import 'package:http/http.dart' as http; class BloodProvider with ChangeNotifier { String? dropdownValue; var bloodList = <Data>[]; // 拉取血型数据 fetchBlood() async { var response = await http.get(Uri.parse(bloodGroupUrl)); var data = jsonDecode(response.body); if (response.statusCode == 200) { BloodGroup bloodGroup = BloodGroup.fromJson(data); bloodList = bloodGroup.data; notifyListeners(); // 成功获取数据后立即通知UI更新 return bloodList; } // 请求失败时也可触发通知或添加错误处理逻辑 notifyListeners(); } setDropdownValue(String? dorpValue) { dropdownValue = dorpValue; notifyListeners(); } }
修正后的Homepage代码
import 'package:api_dropdown/provider/blood_provider.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; class Homepage extends StatefulWidget { const Homepage({super.key}); @override State<Homepage> createState() => _HomepageState(); } class _HomepageState extends State<Homepage> { @override void initState() { // 获取全局注册的Provider实例,而非自行实例化 Provider.of<BloodProvider>(context, listen: false).fetchBlood(); super.initState(); } @override Widget build(BuildContext context) { final provider = Provider.of<BloodProvider>(context); return Scaffold( appBar: AppBar( title: const Text("Api Dropdown"), ), body: Column( children: [ DropdownButtonHideUnderline( child: DropdownButton( icon: const Icon(Icons.keyboard_arrow_down), underline: const SizedBox(), value: provider.dropdownValue, onChanged: (String? newValue) { provider.setDropdownValue(newValue); }, items: provider.bloodList.map((items) { return DropdownMenuItem( value: items.id.toString(), child: Text( items.name.toString(), style: const TextStyle( fontSize: 14, color: Colors.red), )); }).toList(), ), ), TextFormField( enabled: false, decoration: const InputDecoration( contentPadding: EdgeInsets.only(top: 4, left: 8), hintText: "ex: A+", border: OutlineInputBorder()), ), ], ), ); } }
额外注意事项
请确保已在main.dart中正确全局注册Provider,示例代码如下:
void main() { runApp( ChangeNotifierProvider( create: (context) => BloodProvider(), child: const MyApp(), ), ); }
内容的提问来源于stack exchange,提问作者Minhajul Islam Apu
相关产品推荐
相关产品推荐

