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

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"}]}

问题根源

  1. getCountries()是异步函数,initState中调用后会立刻执行_foundCountries = _allCountries,此时API请求尚未完成,_allCountries还是空数组,导致_foundCountries也为空。
  2. API请求完成后更新了_allCountries,但未调用setState()触发UI重建,页面不会感知到数据变化。
  3. 点击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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 23:06:11