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

Flutter开发:多API端点下实现联赛类关联足球赛事实例列表的最优方案

实现带赛事列表的可展开联赛列表的最优方案

我来帮你一步步解决这个问题,从修改数据模型到整合API数据,再到优化方法逻辑:

1. 先修改League类,添加赛事列表属性

当然可以直接在League类里添加List<SoccerMatch>属性,建议初始化一个空列表避免空指针问题,同时更新构造函数和fromJson工厂方法:

class League {
  int id;
  String name;
  String country;
  String logoUrl;
  String flag;
  String season;
  // 添加赛事列表,初始化为空列表
  List<SoccerMatch> matches;

  League(
    this.id,
    this.name,
    this.country,
    this.logoUrl,
    this.flag,
    this.season,
    // 构造函数里初始化matches
    this.matches = const [],
  );

  factory League.fromJson(Map<String, dynamic> json) {
    return League(
      json['league']['id'],
      json['league']['name'],
      json['country']['name'],
      json['league']['logo'],
      json['country']['flag'],
      json['seasons'][0]['year'].toString(),
      // fromJson时先给空列表,后续再填充数据
      [],
    );
  }
}

2. 优化getLeague方法,返回单个League实例

你提到当前返回列表不是最佳实践,因为根据leagueName和country参数,API应该只会返回唯一的联赛数据。我们可以调整方法返回Future<League?>(处理无数据的情况)或者Future<League>(确保有数据,无数据时抛出异常):

Future<League?> getLeague(String leagueName, String country) async {
  Response response = await get(
    Uri.parse(
        "${apiUrl}leagues?current=true&name=$leagueName&country=$country"),
    headers: headers);
  if (response.statusCode == 200) {
    var body = jsonDecode(response.body);
    List<dynamic> leagueList = body['response'];
    if (leagueList.isNotEmpty) {
      return League.fromJson(leagueList.first);
    } else {
      // 没有找到对应联赛时返回null
      return null;
    }
  } else {
    throw Exception('Error accessing API: ${response.statusCode}');
  }
}

如果你的业务场景中必须存在该联赛,也可以在leagueList为空时抛出异常,替换return null为throw Exception('League not found')。

3. 整合两个API的数据,给联赛填充赛事

这里有两种常用的实现方式,根据你的业务场景选择:

方式一:封装一个组合方法,一次性获取联赛+赛事

在SoccerApi里新增一个方法,先获取联赛,再根据联赛ID获取对应的赛事,最后赋值给League的matches属性:

Future<League?> getLeagueWithMatches(String leagueName, String country) async {
  try {
    // 先获取联赛信息
    League? league = await getLeague(leagueName, country);
    if (league == null) return null;
    
    // 根据联赛ID获取赛事列表
    List<SoccerMatch> matches = await getAllMatches(league.id);
    // 给联赛赋值赛事
    league.matches = matches;
    
    return league;
  } catch (e) {
    throw Exception('Failed to fetch league with matches: $e');
  }
}

方式二:在ViewModel/UI层手动组合数据

如果你希望更灵活地控制加载时机(比如先展示联赛列表,用户点击展开时再加载赛事),可以在UI逻辑里先获取联赛,当用户触发展开操作时再调用getAllMatches,然后更新League的matches:

// 示例:在UI逻辑中
void loadLeagueMatches(League league) async {
  try {
    List<SoccerMatch> matches = await soccerApi.getAllMatches(league.id);
    setState(() {
      league.matches = matches;
    });
  } catch (e) {
    // 处理加载失败的情况
    print(e);
  }
}

4. 额外的小优化:处理API返回的空值

注意到你的模型里有些字段可能为null(比如Goal的home/away可能还没有进球数据),建议修改类型为可空,并在fromJson时处理空值,避免运行时错误:

class Goal {
  String? home;
  String? away;
  Goal(this.home, this.away);

  factory Goal.fromJson(Map<String, dynamic> json) {
    return Goal(
      json['home']?.toString(),
      json['away']?.toString(),
    );
  }
}

这样当API返回null时,你的模型不会因为toString()调用而崩溃。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.27 17:47:48