Flutter 中如何从 TheCatAPI 返回的 JSON 数组提取数据实现猫图列表展示
代码核心问题定位
- 返回类型不匹配:Cat API接口返回的是对象数组,原代码的
getPics()方法定义为返回单个CatApi对象,解析时直接将整个数组传给单对象的解析逻辑,无法生成有效数据。 - 接口地址错误:原代码请求的端点不是图片搜索的目标端点,参数格式也不符合接口要求,无法拿到正确的返回数据。
- 冗余无效代码:原代码中保留了未使用的pixabay接口地址变量,无实际执行作用。
- ListView配置缺失:
ListView.builder没有配置itemCount属性,没有明确列表的条目总数,即使拿到数据也无法正常渲染。 - 取值逻辑错误:原代码将解析后的数据当成Map结构,通过
data['url'][index]的方式取图片地址,实际解析结果是对象列表,不存在Map结构的url键,取值必然报错。 - Model类参数顺序错误:
CatApi类的构造函数参数顺序与fromJson方法传参顺序不一致,width和height字段值被颠倒。 - 类型不匹配错误:FutureBuilder的builder内将
snapshot.data强制声明为Map类型,与实际的列表类型不符,直接触发类型转换异常。 - 冗余全局变量:State类中声明的
Map data全局变量无实际作用,还会造成变量名冲突。
修正后的可运行代码
import 'dart:convert'; import 'package:cats_app_new/constants.dart'; import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; class HomeScreen extends StatefulWidget { static const routeName = '/home-screen'; @override _HomeScreenState createState() => _HomeScreenState(); } class _HomeScreenState extends State<HomeScreen> { @override Widget build(BuildContext context) { return FutureBuilder( future: getPics(), builder: (context, snapshot) { // 异常状态展示 if (snapshot.hasError) { return Center( child: Text( 'Failed to get response', style: TextStyle( color: Colors.red, fontSize: 22.0, ), ), ); } // 加载状态展示 if (!snapshot.hasData) { return Center( child: CircularProgressIndicator(), ); } // 正常数据渲染列表 final List<CatApi> catList = snapshot.data; return ListView.builder( itemCount: catList.length, itemBuilder: (context, index) { final currentCat = catList[index]; return Column( children: [ Padding( padding: EdgeInsets.all(kDefaultPadding / 4), ), Container( child: InkWell( onTap: () {}, child: Image.network( currentCat.url, fit: BoxFit.cover, ), ), ), ], ); }, ); }, ); } } Future<List<CatApi>> getPics() async { final requestUri = Uri.parse( 'https://api.thecatapi.com/v1/images/search?api_key=$kApiKey' ); final response = await http.get(requestUri); if (response.statusCode != 200) { throw Exception('网络请求失败,状态码:${response.statusCode}'); } final List responseList = jsonDecode(response.body); return responseList.map( (itemJson) => CatApi.fromJson(itemJson) ).toList(); } class CatApi { String id; String url; int width; int height; CatApi({ required this.id, required this.url, required this.width, required this.height, }); factory CatApi.fromJson(Map<String, dynamic> json) { return CatApi( id: json['id'] as String, url: json['url'] as String, width: json['width'] as int, height: json['height'] as int, ); } @override String toString() { return '{${this.url}}'; } }
关键优化说明
- 解析逻辑完全匹配接口返回的数组结构,遍历数组中每个元素生成对应的
CatApi对象,返回列表类型给FutureBuilder。 ListView.builder补充了itemCount配置,明确列表渲染的条目数量,避免组件渲染异常。- 图片取值直接从对应列表索引的
CatApi对象中读取,不再使用Map结构的错误取值逻辑。 - 网络请求环节补充了状态码判断,遇到非200响应时抛出明确异常,避免将错误页面内容当成JSON解析引发崩溃。
CatApi类改用命名参数构造,避免传参顺序颠倒导致的字段值错误。
内容的提问来源于stack exchange,提问作者Dmitry Zarutsky
相关产品推荐
相关产品推荐

