Flutter 使用Dio请求数据渲染ListView时类型转换错误求解
问题原因与解决方案
- 自定义模型类命名为
List,和Dart SDK自带的集合类型List冲突,导致类型匹配混乱 - Dio库默认会自动将JSON响应解析为Map/List类型,不需要额外调用
jsonDecode,重复解析会触发类型错误 - 没有按照接口实际返回的嵌套结构提取数据:接口返回的员工列表存放在
response.data['data']['data']字段,总数量存放在response.data['data']['count']字段,原代码直接将整个响应传入模型解析,结构不匹配 - 原代码返回类型配置错误,要渲染列表需要返回员工集合,而不是单个员工对象
修正后的完整代码
import 'dart:async'; import 'package:dio/dio.dart'; import 'package:flutter/material.dart'; // 员工模型类,禁止使用List作为自定义类名 class Employee { final int idEmployee; final String fullName; Employee({ required this.idEmployee, required this.fullName, }); factory Employee.fromJson(Map<String, dynamic> json) { return Employee( idEmployee: json['idEmployee'], fullName: json['fullName'], ); } } // 封装接口响应结构,存储总数量和员工列表 class ApiResponse { final int count; final List<Employee> employees; ApiResponse({required this.count, required this.employees}); } Future<ApiResponse> listData() async { final token = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOjI4OTksImlzcyI6Imh0dHBzOi8vcG9ydGFsLWFwaS5qb21ha2hhdGEuY29tL2FwaS9hdXRoL2xvZ2luIiwiaWF0IjoxNjI5NDM2MzA1LCJleHAiOjE2Mjk1MjI3MDUsIm5iZiI6MTYyOTQzNjMwNSwianRpIjoiVWY5cEFBcVVnSG1ZdWlTMyJ9.BAjwiHMNozDWDHHrCP1p7Mt_dsNo_KNYWMQmOCuFhwQ'; String url = 'https://portal-api.jomakhata.com/api/getOrganizationData?token=${token}'; Dio dio = Dio(); dio.options.headers['Content-Type'] = 'application/json'; final body = {'limit': 1, 'orderBy': 'idEmployee', 'orderType': 'DESC'}; final response = await dio.post(url, data: body); if (response.statusCode == 200) { // Dio已自动解析响应为Map类型,无需额外jsonDecode Map resData = response.data; int count = resData['data']['count']; List empList = resData['data']['data']; List<Employee> employees = empList.map((e) => Employee.fromJson(e)).toList(); return ApiResponse(count: count, employees: employees); } else { throw Exception('Failed!'); } } void main() { runApp(MyApp()); } class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( debugShowCheckedModeBanner: false, title: 'Flutter', theme: ThemeData( primarySwatch: Colors.blue, ), home: MyHomePage(title: 'List View'), ); } } class MyHomePage extends StatefulWidget { MyHomePage({Key? key, required this.title}) : super(key: key); final String title; @override _MyHomePageState createState() => _MyHomePageState(); } class _MyHomePageState extends State<MyHomePage> { late Future<ApiResponse> futureData; @override void initState() { super.initState(); futureData = listData(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text(widget.title)), body: Center( child: FutureBuilder<ApiResponse>( future: futureData, builder: (context, snapshot) { if (snapshot.hasData) { return ListView.builder( itemCount: snapshot.data!.employees.length + 1, itemBuilder: (context, index) { // 首项展示总员工数 if (index == 0) { return Padding( padding: EdgeInsets.all(16), child: Text("总员工数:${snapshot.data!.count}", style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)), ); } // 后续项展示员工信息 Employee emp = snapshot.data!.employees[index -1]; return ListTile( title: Text(emp.fullName), subtitle: Text("员工ID:${emp.idEmployee}"), ); }, ); } else if (snapshot.hasError) { return Text('${snapshot.error}'); } return const CircularProgressIndicator(); }, ), ), ); } }
如需展示更多员工字段,只需在Employee模型类中添加对应属性,再修改ListTile的布局即可。
内容的提问来源于stack exchange,提问作者Fozuda
相关产品推荐
相关产品推荐

