Flutter中initState内调用API获取数据不显示的修复方案
问题解决:API获取国家数据初始化后无法显示
开发国家列表页面时,在initState()中调用API获取数据,但数据无法显示。点击TextFormField编辑文本后数据才出现,怀疑是initState中给_foundCountries赋值的环节有问题,求解决办法。
代码片段
class SignUp extends StatefulWidget { const SignUp({super.key}); @override State<SignUp> createState() => _SignUpState(); } class _SignUpState extends State<SignUp> { List _allCountries = []; List _foundCountries = []; bool showDropDown = false; final ApiService _apiService = ApiService(); Future<void> getCountries() async { try { final response = await _apiService.getCountries(); _allCountries = response['list']; log(_allCountries.toString()); } catch (e) { log(e.toString()); rethrow; } } @override void initState() { getCountries(); _foundCountries = _allCountries; super.initState(); } @override Widget build(BuildContext context) { return Scaffold( body: Column( children: [ TextFormField( onTap: () { setState(() { showDropDown = !showDropDown; // _foundCountries = _allCountries; If I try to add this code, data appears when screen is loaded }); }, ), SizedBox( child: showDropDown ? Column( children: [ Flexible( child: ListView.builder( itemCount: _foundCountries.length, itemBuilder: (context, index) { return ListTile( title: Text( _foundCountries[index]['name'] ), ); }, ) ) ], ) : null, ) ], ), ); } }
API响应
{"success":true,"list":[{"id": 1, "name": "Abkhazia"}, {"id":2, "name": "Afghanistan"}]}
问题根源
getCountries()是异步函数,initState中调用后会立刻执行_foundCountries = _allCountries,此时API请求尚未完成,_allCountries还是空数组,导致_foundCountries也为空。- API请求完成后更新了
_allCountries,但未调用setState()触发UI重建,页面不会感知到数据变化。 - 点击TextFormField时触发了
setState(),若此时重新给_foundCountries赋值,就能拿到已填充数据的_allCountries,UI才会显示内容。
修复方案
1. 异步请求完成后同步数据并更新状态
修改getCountries()方法,在获取数据后通过setState()同时更新_allCountries和_foundCountries,触发UI重建:
Future<void> getCountries() async { try { final response = await _apiService.getCountries(); setState(() { _allCountries = response['list']; _foundCountries = _allCountries; // 同步数据到搜索列表 }); log(_allCountries.toString()); } catch (e) { log(e.toString()); rethrow; } }
2. 移除initState中无效赋值
initState里无需再给_foundCountries赋值,API请求完成后会通过setState()同步数据:
@override void initState() { getCountries(); super.initState(); }
3. 可选:添加加载状态优化体验
可以新增加载状态变量,避免用户看到空列表:
// 新增加载状态变量 bool _isLoading = true; Future<void> getCountries() async { try { final response = await _apiService.getCountries(); setState(() { _allCountries = response['list']; _foundCountries = _allCountries; _isLoading = false; // 标记加载完成 }); log(_allCountries.toString()); } catch (e) { log(e.toString()); setState(() { _isLoading = false; // 加载失败也更新状态 }); rethrow; } } // 在build方法中修改列表部分 Flexible( child: _isLoading ? Center(child: CircularProgressIndicator()) : ListView.builder( itemCount: _foundCountries.length, itemBuilder: (context, index) { return ListTile( title: Text(_foundCountries[index]['name']), ); }, ) )
内容的提问来源于stack exchange,提问作者newbie2210
相关产品推荐
相关产品推荐

