Flutter中使用FutureBuilder和Dio无法展示用户列表求助
Flutter中FutureBuilder+Dio加载用户列表失败的排查与解决
问题描述
在Flutter应用中使用FutureBuilder组件结合Dio库发起HTTP请求展示用户列表时,仅显示Failed to load user list提示,无法看到具体错误原因。已完成以下验证:
- API地址正确且可正常访问
- API返回数据格式合法有效
- User类的fromJson反序列化方法逻辑正确
相关代码
UsersList组件代码
import 'package:flutter/material.dart'; import 'package:dio/dio.dart'; import 'dart:convert'; import 'package:larpland/model/user.dart'; class UsersList extends StatefulWidget { const UsersList({super.key}); @override State<UsersList> createState() => _UsersListState(); } class _UsersListState extends State<UsersList> { late Future<List<User>> futureUserList; @override void initState() { super.initState(); futureUserList = fetchUserList(); } @override Widget build(BuildContext context) { return FutureBuilder<List<User>>( future: futureUserList, builder: (context, snapshot) { if (snapshot.hasData) { return ListView.builder( itemCount: snapshot.data!.length, itemBuilder: (context, index) { return ListTile( title: Text(snapshot.data![index].name), subtitle: Text(snapshot.data![index].email), ); }, ); } else if (snapshot.hasError) { return const Center( child: Text('Failed to load user list'), ); } return const Center( child: CircularProgressIndicator(), ); }, ); } Future<List<User>> fetchUserList() async { final response = await Dio().get('https://10.0.2.2:8000/api/users'); if (response.statusCode == 200) { return List<User>.from(jsonDecode(response.data).map((user) => User.fromJson(user))); } else { throw Exception('Failed to fetch user list'); } } }
User模型代码
class User { final int id; final String name; final String email; final String password; final int rol; const User({ required this.id, required this.name, required this.email, required this.password, required this.rol, }); factory User.fromJson(Map<String, dynamic> json) { return switch (json) { { 'id': int id, 'name': String name, 'email': String email, 'password': String password, 'rol': int rol, } => User( id: id, name: name, email: email, password: password, rol: rol, ), _ => throw const FormatException('Failed to load users'), }; } }
排查与解决步骤
1. 先获取具体错误信息
当前错误提示过于笼统,修改FutureBuilder的错误分支,直接打印异常详情:
else if (snapshot.hasError) { return Center( child: Text('加载失败: ${snapshot.error.toString()}'), ); }
运行后即可看到具体错误类型(网络错误/序列化错误等),针对性排查。
2. 修正Dio响应解析逻辑
Dio默认会自动将JSON响应解析为Map或List,无需再调用jsonDecode,原代码的重复解析会导致类型错误,修改fetchUserList方法:
Future<List<User>> fetchUserList() async { final response = await Dio().get('https://10.0.2.2:8000/api/users'); if (response.statusCode == 200) { // 直接使用response.data,无需jsonDecode return List<User>.from((response.data as List).map((user) => User.fromJson(user))); } else { throw Exception('请求失败: ${response.statusCode}'); } }
3. 兼容API返回字段的潜在问题
检查API返回字段是否与User类完全匹配:
- 确认
rol字段为数字类型,若API返回字符串需转为int - 若API可能不返回
password字段,修改User类允许该参数为空:
// 修改User构造函数 const User({ required this.id, required this.name, required this.email, this.password = '', // 设置默认值,转为可选参数 required this.rol, }); // 修改fromJson的switch表达式 factory User.fromJson(Map<String, dynamic> json) { return switch (json) { { 'id': int id, 'name': String name, 'email': String email, 'password': String? password, // 允许空值 'rol': int rol, } => User( id: id, name: name, email: email, password: password ?? '', // 空值时用默认值 rol: rol, ), _ => throw const FormatException('Failed to load users'), }; }
4. 捕获Dio专属异常
添加Dio异常捕获,处理网络连接、证书、超时等问题:
Future<List<User>> fetchUserList() async { try { final response = await Dio().get('https://10.0.2.2:8000/api/users'); if (response.statusCode == 200) { return List<User>.from((response.data as List).map((user) => User.fromJson(user))); } else { throw Exception('请求失败: ${response.statusCode}'); } } on DioException catch (e) { // 捕获Dio专属异常,输出详细信息 throw Exception('网络错误: ${e.message}'); } catch (e) { // 捕获其他未知异常 throw Exception('未知错误: $e'); } }
内容的提问来源于stack exchange,提问作者juan manuel jimenez
相关产品推荐
相关产品推荐

