Flutter调用API触发Unexpected null value错误,请求排查
Flutter调用API时出现Unexpected null value错误的解决方案
问题描述
调用API获取单个坐骑数据时,持续触发Unexpected null value错误,无法正常加载数据。API返回的JSON结构如下:
{ "id": 257, "name": "Island Eggplant Knight", "description": "Summon forth your island Eggplant Knight, an oversized vegetable embodiment of chivalry.", "enhanced_description": "Hailing from the selfsame land as the Tomato King, the Eggplant Knight shared a crate with the sovereign when they were shipped out. However, he fell overboard when the vessel encountered rough seas, and drifted for days before being deposited on a desert island. Among other feats, he prides himself on having played a key role in the founding of the West Mandra Empire.", "tooltip": "I thought ye were a feral turnip, a murderous eggplant, or summat like that! - Tiny Trader", "movement": "Terrestrial", "seats": 1, "order": 240, "order_group": 99, "patch": "6.2", "item_id": null, "tradeable": false, "owned": "3.9%", "image": "https://ffxivcollect.com/images/mounts/large/257.png", "icon": "https://ffxivcollect.com/images/mounts/small/257.png", "bgm": "https://ffxivcollect.com/music/BGM_Ride_MJI.ogg", "sources": [ { "type": "Purchase", "text": "12,000 Seafarer's Cowries", "related_type": null, "related_id": null } ] }
错误核心原因
- API响应格式与解析逻辑不匹配:该API返回的是单个对象,但你的模型解析代码强制将其转为List
,导致 json.decode(str).map执行时因单个对象无map方法抛出空值异常。 - 服务层返回类型错误:
RemoteService.getPosts声明返回Future<List<FinalApi>>,但实际应返回单个FinalApi实例。 - UI层依赖错误数据类型:Home页面用
finalApi!.length获取列表长度,但finalApi实际是单个对象,强制解包触发空值错误。
修复步骤
1. 修改模型解析代码
将列表解析改为单个对象解析:
// 替换原有的列表解析方法 FinalApi finalApiFromJson(String str) => FinalApi.fromJson(json.decode(str)); String finalApiToJson(FinalApi data) => json.encode(data.toJson());
2. 修正RemoteService代码
调整返回类型并修正解析逻辑:
class RemoteService { Future<FinalApi> getPost() async { var client = http.Client(); var uri = Uri.parse('https://ffxivcollect.com/api/mounts/257'); var response = await client.get(uri); if (response.statusCode == 200) { var json = response.body; return finalApiFromJson(json); } throw Exception('请求失败'); } }
3. 调整Home页面UI代码
因数据为单个对象,无需使用ListView.builder,直接展示数据(建议搭配FutureBuilder处理异步加载):
Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('')), body: FutureBuilder<FinalApi>( future: RemoteService().getPost(), builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.waiting) { return const Center(child: CircularProgressIndicator()); } else if (snapshot.hasError) { return Center(child: Text('错误: ${snapshot.error}')); } else if (snapshot.hasData) { return Container(child: Text(snapshot.data!.description)); } else { return const Center(child: Text('无数据')); } }, ), ); }
4. 优化模型类型安全性(可选)
将dynamic itemId改为int? itemId,明确字段可为空,增强代码健壮性:
class FinalApi { // ...其他字段 int? itemId; FinalApi({ // ...其他required参数 required this.itemId, // ...其他参数 }); factory FinalApi.fromJson(Map<String, dynamic> json) => FinalApi( // ...其他字段赋值 itemId: json["item_id"], // ...其他赋值 ); }
内容的提问来源于stack exchange,提问作者yuuu
相关产品推荐
相关产品推荐

