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

Flutter中ListView调用API后仅显示CircularProgressIndicator白屏问题修复求助

问题修复方案:Flutter ListView 调用API后白屏加载不结束

我帮你定位到了问题的核心——counter变量的赋值顺序错误,导致它始终为null,页面永远无法触发ListView的渲染,一直停留在加载状态。下面详细拆解问题并给出修复方案:

问题根源分析

在你的callHaber方法中,你先尝试用旧的haberResult(此时还是null)去赋值counter,之后才更新haberResult:

setState(() {
  counter = haberResult?.rss.channel.item.length; // 这时候haberResult还是null,counter会变成null
  haberResult = rss;
});

再加上你用counter != null作为ListView的显示条件,这就导致ListView永远不会被渲染,页面一直显示CircularProgressIndicator。另外if(mounted);后面多了个分号,这行代码完全没有生效,属于无效写法。


修复步骤

方案1:调整赋值顺序(最小改动)

先更新haberResult,再用新数据赋值counter,同时去掉多余的分号:

Future callHaber() async {
  try{
    final response = await http.get(url);
    if(response.statusCode == 200){
      var rss = economylistXmlFromJson(response.body);
      if(mounted){ // 去掉多余的分号
        setState(() {
          haberResult = rss; // 先更新数据源
          counter = haberResult?.rss.channel.item.length; // 再基于新数据获取长度
        });
      }
      return rss;
    } else {
      print('请求失败,状态码:${response.statusCode}');
    }
  } catch(e) {
    print('请求出错:${e.toString()}');
  }
}

方案2:移除counter变量(更简洁健壮)

其实完全不需要额外维护counter变量,直接用haberResult的数据长度作为ListView的itemCount,这样能避免变量同步问题:
修改build方法中的body部分:

body: Center(
  child: Padding(
    padding: const EdgeInsets.all(8.0),
    child: haberResult != null ? ListView.builder(
        itemCount: haberResult!.rss.channel.item.length,
        itemBuilder: (context, index){
          final newsItem = haberResult!.rss.channel.item[index];
          return Card(
            child: ListTile(
              title: Text(newsItem.title ?? ""),
              onTap: () => Navigator.push(
                context,
                MaterialPageRoute(builder: (context) => HaberDetailScreen(
                  subtitle: newsItem.title ?? "",
                  title: newsItem.description ?? "",
                )),
              ),
            ),
          );
        }) : const Center(child: CircularProgressIndicator()),
  ),
),

方案3:使用FutureBuilder(推荐最佳实践)

手动维护haberResult和状态容易出错,用FutureBuilder可以自动处理异步请求的各种状态(加载中、成功、失败),代码更简洁健壮:

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      centerTitle: false,
      automaticallyImplyLeading: false,
      title: const Text('Ekonomi Haberleri'),
    ),
    body: FutureBuilder<EconomylistXml>(
      future: callHaber(),
      builder: (context, snapshot) {
        if (snapshot.connectionState == ConnectionState.waiting) {
          return const Center(child: CircularProgressIndicator());
        } else if (snapshot.hasError) {
          return Center(child: Text('加载出错:${snapshot.error}'));
        } else if (!snapshot.hasData || snapshot.data?.rss.channel.item.isEmpty == true) {
          return const Center(child: Text('没有找到新闻数据'));
        } else {
          final newsItems = snapshot.data!.rss.channel.item;
          return Padding(
            padding: const EdgeInsets.all(8.0),
            child: ListView.builder(
              itemCount: newsItems.length,
              itemBuilder: (context, index) {
                final item = newsItems[index];
                return Card(
                  child: ListTile(
                    title: Text(item.title ?? ""),
                    onTap: () => Navigator.push(
                      context,
                      MaterialPageRoute(builder: (context) => HaberDetailScreen(
                        subtitle: item.title ?? "",
                        title: item.description ?? "",
                      )),
                    ),
                  ),
                );
              },
            ),
          );
        }
      },
    ),
  );
}

使用这个方案后,你可以移除haberResult和counter变量,callHaber方法只需返回请求结果即可,不用再手动调用setState。


额外注意事项

  • 确保API返回的JSON结构和你的数据模型完全匹配,比如rss.channel.item确实是数组类型,避免解析后出现空列表的情况。
  • 记得在initState中初始化ScrollController:controller = ScrollController();,避免空安全警告。
  • 可以添加网络请求失败的UI提示,让用户知道发生了什么,而不是一直显示加载动画。

内容的提问来源于stack exchange,提问作者Mıktad Tahir Durak

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.27 18:37:50