Flutter中FutureBuilder获取JSON数据始终返回Null无报错如何解决
问题排查及修复方案
核心问题点
- FutureBuilder逻辑错误:snapshot.hasData为true的分支下直接创建了空的
Analysts对象,完全没有读取snapshot.data中接口返回的列表数据,空对象属性默认全为null,自然始终显示Error。 - 模型类不符合空安全规范:Dart空安全下声明的
String非空属性,构造函数却将所有参数设为可选且无默认值,逻辑矛盾会引发编译/运行异常。 - 泛型声明语法错误:
fromJson和parseAnalysis方法中Map泛型错误写为Map<"String", dynamic>,多余的引号会导致JSON解析时类型匹配失败。 - JSON解析缺少空值处理:直接对JSON字段调用
toString()、强制as String转换,若对应字段不存在或为null时会直接抛出异常,且你未在FutureBuilder中捕获错误导致问题被掩盖。 - 缺少异常分支处理:原有FutureBuilder只判断了hasData状态,未处理加载中、请求失败的场景,无法暴露潜在的请求/解析错误。
修复后代码
1. FutureBuilder部分
FutureBuilder<List<Analysts>>( future: iexcloudanalysts.getData(), builder: (context, snapshot) { // 加载中状态 if (snapshot.connectionState == ConnectionState.waiting) { return const CircularProgressIndicator(color: Colors.white); } // 请求错误状态 if (snapshot.hasError) { return Text( '请求错误:${snapshot.error}', style: const TextStyle(color: Colors.white, fontSize: 16), ); } // 正常返回数据 if (snapshot.hasData && snapshot.data!.isNotEmpty) { // 取列表第一条数据,可根据业务需求调整取值逻辑 Analysts analysts = snapshot.data!.first; return Text( analysts.consensusDate ?? 'Error', style: const TextStyle( color: Colors.white, fontSize: 32, fontWeight: FontWeight.bold, ), ); } return const Text('无数据', style: TextStyle(color: Colors.white)); }, )
2. Analysts模型类
class Analysts { // 改为可空类型适配空安全 final String? analystCount; final String? consensusDate; final String? marketConsensus; final String? marketConsensusTargetPrice; Analysts({ this.analystCount, this.consensusDate, this.marketConsensus, this.marketConsensusTargetPrice, }); // 修正Map泛型,添加空值安全处理 factory Analysts.fromJson(Map<String, dynamic> json) { return Analysts( analystCount: json['analystCount']?.toString(), consensusDate: json['consensusDate'] as String?, marketConsensus: json['marketConsensus']?.toString(), marketConsensusTargetPrice: json['marketConsensusTargetPrice']?.toString(), ); } }
3. 网络请求与解析部分
class IEXCloudServiceAnalysts { Future<List<Analysts>> getData() async{ var url = Uri.parse("https://sandbox.iexapis.com/stable/time-series/CORE_ESTIMATES/TSLA?token=Tpk_85b3b5cdb32147d3a0fb751cc5176cdd"); Response res = await get(url); // 新增状态码判断,提前抛出请求异常 if (res.statusCode == 200) { return parseAnalysis(res.body); } else { throw Exception("请求失败,状态码:${res.statusCode}"); } } } // 修正Map泛型声明 List<Analysts> parseAnalysis(String responseBody) { final parsed = jsonDecode(responseBody).cast<Map<String, dynamic>>(); return parsed.map<Analysts>((json) => Analysts.fromJson(json)).toList(); }
内容的提问来源于stack exchange,提问作者tobsq
相关产品推荐
相关产品推荐

