Flutter中HTTP GET请求返回null问题排查与解决
问题排查与解决方案
核心问题分析
- JSON字段不匹配:返回的JSON根字段是
"client"(单数),但Client模型的fromJson方法里读取的是"clients"(复数),导致解析后clients列表始终为null。 - API解析逻辑错误:
fetchClient函数错误地将整个响应数据当成数组遍历,实际响应是一个包含client数组的对象,遍历逻辑完全错误。 - FutureBuilder未处理状态:直接访问
snapshot.data.length,没有判断snapshot是否完成、是否有数据,当请求未完成或解析失败时,snapshot.data为null,触发NoSuchMethodError。
分步修复
1. 修正Client模型的JSON字段匹配
修改Client类的fromJson方法,将json['clients']改为json['client'],对应返回的JSON根字段:
class Client { List<Clients>? clients; Client({required this.clients}); Client.fromJson(Map<String, dynamic> json) { if (json['client'] != null) { // 从clients改为client,匹配返回的JSON字段 clients = <Clients>[]; json['client'].forEach((v) { clients?.add(new Clients.fromJson(v)); }); } } Map<String, dynamic> toJson() { final Map<String, dynamic> data = new Map<String, dynamic>(); if (this.clients != null) { data['clients'] = this.clients!.map((v) => v.toJson()).toList(); } return data; } }
2. 重构API调用逻辑
整个响应对应一个Client对象,里面包含List<Clients>,调整函数返回类型并修正解析逻辑:
Future<Client> fetchClient() async { Uri url = Uri.parse("${BASE_URL}client"); var response = await http.get(url, headers: <String, String>{ 'Content-Type': 'application/json; charset=UTF-8', 'Authorization': 'Bearer $TOKEN', }); if (response.statusCode == 200) { var data = json.decode(response.body); return Client.fromJson(data); // 直接用模型的fromJson解析整个响应 } else { throw Exception('Failed to load clients'); } }
3. 修复FutureBuilder的状态处理
在builder中先判断snapshot的状态,处理加载中、错误、无数据的情况,再安全访问数据:
return FutureBuilder<Client>( future: fetchClient(), builder: (context, AsyncSnapshot<Client> snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { return const Center(child: CircularProgressIndicator()); } else if (snapshot.hasError) { return Center(child: Text('Error: ${snapshot.error}')); } else if (!snapshot.hasData || snapshot.data?.clients == null || snapshot.data!.clients!.isEmpty) { return const Center(child: Text('No clients found')); } else { return ListView.builder( itemCount: snapshot.data!.clients!.length, itemBuilder: (context, index) { final client = snapshot.data!.clients![index]; return ListTile( title: Text(client.name ?? 'Unknown'), subtitle: Text(client.address ?? 'No address'), ); }); } }, );
额外优化建议
- 模型命名优化:把
Clients改为ClientItem,避免和外层Client类混淆,减少代码歧义。 - 使用
json_serializable包自动生成JSON解析代码,避免手动编写时的字段匹配错误。
内容的提问来源于stack exchange,提问作者mobix
相关产品推荐
相关产品推荐

