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

Flutter中FutureBuilder返回空列表,response.body数据正常问题排查

排查Flutter FutureBuilder返回空列表的问题

结合你描述的场景(接口返回数据正确但FutureBuilder始终拿空列表),从以下几个核心方向排查:


1. 确认JSON结构与Model解析的匹配性

首先检查接口返回的JSON层级,是否存在外层包裹对象而非直接返回数组。比如常见的接口结构:

{
  "code": 200,
  "message": "success",
  "data": [{"id":1, "name":"GameA"}, {"id":2, "name":"GameB"}]
}

如果你的Provider代码直接把整个响应体解析为数组,就会因为外层是Map而非List导致解析失败,最终返回空列表:

// 错误写法:直接解析整个响应
return List<GameModel>.from(jsonDecode(response.body).map((x) => GameModel.fromJson(x)));

// 正确写法:先提取内层列表字段
final decoded = jsonDecode(response.body);
return List<GameModel>.from(decoded['data'].map((x) => GameModel.fromJson(x)));

2. 检查GameModel的fromJson方法

确保Model的字段与JSON完全对应,包括字段名、数据类型:

  • 字段名大小写/下划线是否一致:比如JSON里是game_name,Model里不能写gameName(除非用@JsonKey(name: "game_name")注解)
  • 数据类型匹配:比如JSON里id是数字类型,Model里不能用String接收
  • 必填字段是否处理:如果JSON里有非空字段,Model里未正确赋值会导致解析失败,进而整个列表为空

示例错误写法:

class GameModel {
  final String name;
  GameModel({required this.name});
  
  factory GameModel.fromJson(Map<String, dynamic> json) {
    return GameModel(
      name: json['gameName'], // JSON里实际是game_name,导致name为null
    );
  }
}

3. 排查Provider请求代码的异常处理

如果请求代码中吞掉了解析异常,会导致返回空列表而非抛出错误,难以定位问题:

// 错误写法:异常时直接返回空列表
Future<List<GameModel>> fetchGames() async {
  try {
    final response = await http.get(Uri.parse("your_url"));
    final decoded = jsonDecode(response.body);
    return List<GameModel>.from(decoded['data'].map((x) => GameModel.fromJson(x)));
  } catch (e) {
    print(e); // 务必打印错误信息
    return []; // 这里返回空列表会掩盖问题
  }
}

建议异常时直接抛出,让FutureBuilder的snapshot.hasError捕获,方便排查:

catch (e) {
  print("解析错误:$e");
  throw Exception("加载游戏列表失败:$e");
}

4. 检查FutureBuilder的使用是否合理

避免每次build时重新创建Future,导致请求重复触发、状态重置:

// 错误写法:每次build都调用fetchGames(),导致Future重置
FutureBuilder<List<GameModel>>(
  future: Provider.of<GameProvider>(context).fetchGames(),
  builder: (context, snapshot) { ... }
)

// 正确写法:将Future存到State中
class _YourPageState extends State<YourPage> {
  late final Future<List<GameModel>> _gameFuture;

  @override
  void initState() {
    super.initState();
    _gameFuture = Provider.of<GameProvider>(context, listen: false).fetchGames();
  }

  @override
  Widget build(BuildContext context) {
    return FutureBuilder<List<GameModel>>(
      future: _gameFuture,
      builder: (context, snapshot) { ... }
    );
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 23:48:15