Flutter ListView无法展示API返回响应数据的问题求助
问题排查结论
页面空白和ListView布局没关系,核心是数据链路全程断了:
initState里给objectList赋值的代码被你注释了,就算放开也没用,signInData方法定义的返回值是void,根本拿不到解析后的数据- 接口返回200之后你直接跳转到无参的
ResultsPage,既没解析接口返回的JSON,也没把数据传给结果页,结果页初始化时objectList永远是空数组,itemCount为0自然什么都渲染不出来 - 接口响应数据你只做了打印,完全没执行JSON转
CarDetails模型的步骤,数据拿到就丢了
修复方案
1. 改造接口请求方法,补全数据解析逻辑
把signInData的返回值改成Future<List<CarDetails>>,请求成功后先解析数据再返回,不要在请求方法里直接写跳页逻辑:
Future<List<CarDetails>> signInData([data]) async { final prefs = await SharedPreferences.getInstance(); final String? token = prefs.getString('token'); List<CarDetails> carList = []; try { Response response = await _dio.post('$_baseUrl/api/gateway', data: { "ClientPackageId": "0cdd231a-d7ad-4a68-a934-d373affb5100", "PlatformId": "ios", "ClientUserId": "AhmedOmar", "VinNumber": VINumber }, options: Options(headers: { "Content-Type": "application/json", "Authorization": "Bearer $token", })); debugPrint(response.data.toString()); debugPrint('请求状态码:${response.statusCode}'); if (response.statusCode == 200) { // 注意:这里取列表的字段路径要和你实际接口返回结构对齐,比如接口直接返回数组就写response.data as List,如果是包在data字段里就按下面的写法 List responseData = response.data['data'] as List; carList = responseData.map((item) => CarDetails.fromJson(item)).toList(); } else if (response.statusCode == 500) { await getToken(); carList = await signInData(data); } } catch (e) { debugPrint('请求报错:$e'); } return carList; }
2. 选一种方式给结果页传递/加载数据
方式一:跳页时直接传入解析好的数据
接口请求拿到carList之后,跳页时把数据当参数传给ResultsPage:
// 原来写在请求成功后的跳页逻辑改成这样 List<CarDetails> carList = await signInData(); if(carList.isNotEmpty && mounted) { Navigator.of(context).pushReplacement( MaterialPageRoute( builder: (context) => ResultsPage(carList: carList), ), ); }
对应修改ResultsPage的代码接收参数:
class ResultsPage extends StatefulWidget { final List<CarDetails> carList; const ResultsPage({Key? key, required this.carList}) : super(key: key); @override _ResultsPageState createState() => _ResultsPageState(); } class _ResultsPageState extends State<ResultsPage> { late List<CarDetails> objectList; @override void initState() { super.initState(); objectList = widget.carList; } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(), body: Column( children: [ Expanded( // 这里shrinkWrap: true可以删掉,Expanded子组件占满剩余空间,开shrinkWrap反而冗余 child: ListView.builder( itemCount: objectList.length, itemBuilder: (context, index) { return Padding( padding: const EdgeInsets.all(10), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ const Text("Make"), Text(objectList[index].make ?? ''), ], ), ); }, ), ), ], ), ); } }
方式二:直接在ResultsPage初始化时拉取数据
不想传参的话就把请求逻辑放到结果页里,加载完调用setState刷新:
class _ResultsPageState extends State<ResultsPage> { List<CarDetails> objectList = []; bool isLoading = true; @override void initState() { super.initState(); _loadCarData(); } Future<void> _loadCarData() async { objectList = await signInData(); isLoading = false; if(mounted) setState(() {}); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(), body: isLoading ? const Center(child: CircularProgressIndicator()) : Column( children: [ Expanded( child: ListView.builder( itemCount: objectList.length, itemBuilder: (context, index) { return Padding( padding: const EdgeInsets.all(10), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ const Text("Make"), Text(objectList[index].make ?? ''), ], ), ); }, ), ), ], ), ); } }
3. 其他要改的小问题
- 数据模型里
fueType是拼写错误,应该是fuelType,对应fromJson里的key也要确认是不是fuel_type,不然这个字段永远取不到值 - 用可空类型的字段做Text组件入参的时候,别直接调
toString(),加个空判断给默认空字符串,避免字段为null的时候显示"null"文本 - 异步更新UI前一定要判断
mounted属性,避免组件销毁后调用setState触发内存泄漏和报错
内容的提问来源于stack exchange,提问作者SaDev
相关产品推荐
相关产品推荐

