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

Flutter中数组结构API数据无法在ListView.builder展示问题排查

问题解决:Flutter数组结构API数据无法在ListView展示

问题背景

开发Flutter移动端应用,输入名称获取API数据。原本单对象结构的API能正常工作,但切换为返回数组结构的API后,页面仅显示头像图片,ListView无数据加载。尝试过FutureBuilder和GridViewBuilder均无效,怀疑问题出在API返回的数组结构处理上。

API示例

正常工作的单对象API

{"id":"Pw_wOwAmqDmB3slQO_8PkKXLoE56qnBk5f-qdW0fKVTfvAmm",
"accountId":"_MkPpRhr6tK22xRT8TofYHPyACcmURn0cp-U9GbL1xTQzhRfvaw4ZF7P",
"puuid":"RT0wLpw9fOUMgB4HUWDVoMi6_F20W4yhut5-q1bA7Izhl3dPjv5iF2JzqXkLQJYPtf2MBMcvooMmGA",
"name":"Zeri outplay",
"profileIconId":5610,"revisionDate":1669140463310,
"summonerLevel":535}

无法正常工作的数组结构API

[{"leagueId":"e6a38c93-6037-4457-aa57-80a9a52be3ea",
"queueType":"RANKED_SOLO_5x5",
"tier":"PLATINUM","rank":"IV",
"summonerId":"Pw_wOwAmqDmB3slQO_8PkKXLoE56qnBk5f-qdW0fKVTfvAmm",
"summonerName":"Zeri outplay",
"leaguePoints":0,
"wins":75,
"losses":56,
"veteran":false,
"inactive":false,
"freshBlood":false,
"hotStreak":false},
{"leagueId":"a21014e6-fa8f-4f07-b533-b09a10b88bbf",
"queueType":"RANKED_FLEX_SR",
"tier":"SILVER","rank":"II",
"summonerId":"Pw_wOwAmqDmB3slQO_8PkKXLoE56qnBk5f-qdW0fKVTfvAmm",
"summonerName":"Zeri outplay",
"leaguePoints":1,
"wins":15,
"losses":5,
"veteran":false,
"inactive":false,
"freshBlood":false,
"hotStreak":true}]

现有代码

RemoteService.dart

class SummonerRankApi {
  static Future getSummonerRank(summonerid) {
    String link = 'https://euw1.api.riotgames.com/lol/league/v4/entries/by-summoner/$summonerid?api_key=$apiKey';
    return http.get(Uri.parse(link));
  }
}

Home_page.dart

class SummonerProfileRoute extends StatefulWidget {
  String name, summonerId;
  int profileIconId;
  SummonerProfileRoute(this.name, this.summonerId, this.profileIconId);

  @override
  State<StatefulWidget> createState() {
    return _SummonerProfileRouteState(this.name, this.summonerId, this.profileIconId);
  }}

class _SummonerProfileRouteState extends State<SummonerProfileRoute> {
  List<SummonerRank> SummonerRankList = <SummonerRank>[];

  void getSummonerRankfromApi() async {
    SummonerRankApi.getSummonerRank(summonerId).then((response) {
      setState(() {
        Iterable list = json.decode(response.body);
        SummonerRankList = list.map((model) => SummonerRank.fromJson(model)).toList();
      });
    });
  }

  String name, summonerId;
  int profileIconId;
  _SummonerProfileRouteState(this.name, this.summonerId, this.profileIconId);

  @override
  void initState() {
    super.initState();
    getSummonerRankfromApi();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Second Route'),
      ),
      body: Center(
          child: Column(
            children: [
              Image(
                image: NetworkImage('https://ddragon.leagueoflegends.com/cdn/12.22.1/img/profileicon/$profileIconId.png'),
                height: 100,
                width: 100,
              ),
              ListView.builder(
                  itemCount: SummonerRankList.length,
                  itemBuilder: (context, index) {
                    return ListTile(
                      title: Text(SummonerRankList[index].tier),
                      subtitle: Text(SummonerRankList[index].summonerName),
                    );
                  }),
            ],
          )
      ),
    );
  }
}

summoner.dart

class SummonerRank {
  String leagueId;
  String queueType;
  String tier;
  String rank;
  String summonerId;
  String summonerName;
  int leaguePoints;
  int wins;
  int losses;
  bool veteran;
  bool inactive;
  bool freshBlood;
  bool hotStreak;

  SummonerRank.fromJson(Map json)
      : leagueId = json['leagueId'],
        queueType = json['queueType'],
        tier = json['tier'],
        rank = json['rank'],
        summonerId = json['summonerId'],
        summonerName = json['summonerName'],
        leaguePoints = json['leaguePoints'],
        wins = json['wins'],
        losses = json['losses'],
        veteran = json['veteran'],
        inactive = json['inactive'],
        freshBlood = json['freshBlood'],
        hotStreak = json['hotStreak'];

  Map toJson() {
    return {'leagueId': leagueId, 'queueType': queueType, 'tier': tier, 'rank': rank,
      'summonerId': summonerId, 'summonerName': summonerName, 'leaguePoints': leaguePoints, 'wins': wins,
      'losses': losses, 'veteran': veteran, 'inactive': inactive, 'freshBlood': freshBlood, 'hotStreak': hotStreak};
  }
}

问题原因及解决方案

核心问题

ListView放在Column中没有设置高度约束,且未添加shrinkWrap: true或包裹在Expanded组件内,导致ListView无法正常渲染空间。和API数组结构无关,是布局问题。

修复步骤

  1. 给ListView添加约束:在Column中,用Expanded包裹ListView,让它占据剩余空间;或者设置shrinkWrap: true并指定固定高度。
  2. 优化API请求处理:添加错误捕获,避免请求失败时无反馈。

修改后的Home_page.dart关键代码

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: const Text('Second Route'),
    ),
    body: Column(
      children: [
        Image(
          image: NetworkImage('https://ddragon.leagueoflegends.com/cdn/12.22.1/img/profileicon/$profileIconId.png'),
          height: 100,
          width: 100,
        ),
        // 用Expanded包裹ListView,让它占据剩余空间
        Expanded(
          child: ListView.builder(
              itemCount: SummonerRankList.length,
              itemBuilder: (context, index) {
                return ListTile(
                  title: Text(SummonerRankList[index].tier),
                  subtitle: Text(SummonerRankList[index].summonerName),
                );
              }),
        ),
      ],
    ),
  );
}

额外优化:添加错误处理和加载状态

void getSummonerRankfromApi() async {
  try {
    final response = await SummonerRankApi.getSummonerRank(summonerId);
    if (response.statusCode == 200) {
      setState(() {
        Iterable list = json.decode(response.body);
        SummonerRankList = list.map((model) => SummonerRank.fromJson(model)).toList();
      });
    } else {
      // 处理请求失败情况
      print('请求失败,状态码:${response.statusCode}');
    }
  } catch (e) {
    print('请求异常:$e');
  }
}

内容的提问来源于stack exchange,提问作者moosiker

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 17:55:17