Flutter从自建API拉取数据报map在null上调用的NoSuchMethodError错误
报错根因
根据堆栈信息可以直接定位到:报错发生在Wallet.fromJson方法第23行,执行json["account"].map()操作时,取到的json["account"]值是null。Dart中不允许在null对象上调用实例方法,因此直接抛出NoSuchMethodError。
常见的触发场景包括:
- 接口实际返回的JSON结构和代码解析逻辑不匹配,比如字段名拼写不一致、大小写差异、单复数区别,代码读取的
account字段在返回结果中根本不存在 - 接口返回的
account字段本身的值就是null,没有携带账户列表数据 - 请求地址配置错误,实际拿到的不是预期的JSON响应(比如404错误页、接口返回的纯文本),解析后结构完全对不上
- 移动端/模拟器的本地服务地址映射错误,访问
localhost时没有拿到你本地后端服务的返回内容
分步修复操作
1. 先核对接口真实返回内容
不要跳过响应校验直接做JSON解析。在调用walletFromJson的位置,先打印接口的状态码和原始返回内容:
final response = await http.get('http://localhost:3000/list'); // 新增打印校验 print('接口响应状态码:${response.statusCode}'); print('接口原始返回:${response.body}'); final readResponseModel = walletFromJson(response.body);
核对打印出来的JSON字段名,和代码里写的取键名逐字对比,匹配实际的结构调整解析逻辑。
2. 给模型类增加空值兜底
原代码中对json["account"]的取值没有做空判断,只要字段为null就会触发map调用崩溃。修改Wallet类的factory构造函数:
把原来的account赋值逻辑:
account: List<Account>.from(json["account"].map((x) => Account.fromJson(x))),
替换为带空判断的兜底逻辑:
account: json["account"] == null ? [] // 字段为null时返回空列表,不触发map调用 : List<Account>.from(json["account"].map((x) => Account.fromJson(x))),
*如果核对后发现接口返回的账户列表是直接放在根层级(没有外层的seed、account嵌套结构),比如返回结构直接是账户数组[{"privateKey":"xxx", "address":"xxx"}, ...],那原来的Wallet嵌套解析逻辑本身就是错误的,需要对应调整取值方式,不要硬套不匹配的模型结构。
3. 修正本地开发的接口访问地址
Flutter开发中访问localhost是高频踩坑点:
- 安卓模拟器环境下,
localhost指向模拟器自身的环回地址,要替换为10.0.2.2才能访问到主机电脑上的本地服务 - 真机调试时,不能使用localhost,需要填写主机电脑的局域网IP地址(如192.168.3.xx)
- 安卓端需要在AndroidManifest的application节点添加
android:usesCleartextTraffic="true"配置,允许http明文请求,否则请求会被系统安全策略拦截
4. 给数据拉取逻辑增加异常捕获
优化fetchData方法,增加状态判断、异常捕获和组件挂载校验,避免未处理的异步崩溃:
fetchData() async { if (isLoading) return; setState(() { isLoading = true; }); try { final response = await http.get('http://localhost:3000/list'); if (response.statusCode != 200) { throw Exception('请求失败,状态码:${response.statusCode}'); } final readResponseModel = walletFromJson(response.body); list = readResponseModel.account; } catch (e) { // 捕获所有解析、请求类异常,记录错误日志 print('拉取数据失败:$e'); list = []; } finally { // 校验组件是否还处于挂载状态,避免setState报错 if (mounted) { setState(() { isLoading = false; }); } } }
内容的提问来源于stack exchange,提问作者Josue Guessennd
相关产品推荐
相关产品推荐

