Flutter调用API获取数据后页面显示空白屏幕问题求助
问题根因
页面显示空白/持续加载是4处逻辑错误导致的:
- 结果页API实例未初始化:
ResultsPage中声明的_APIState? api从未赋值,initState执行objectList = api?.signInData()时,因为api为null,最终objectList被赋值为null。FutureBuilder绑定null的future后,永远等不到数据返回,自然无法渲染内容。 - 跳转时机完全错误:你在
signInData方法中检测到200状态码就立刻跳转结果页,既没有等待接口数据解析完成,也没有把解析到的车辆数据传递给结果页,后续return CarDetails.fromJson(...)的返回值没有任何组件接收,等于白解析。 - 500状态码递归请求丢失返回值:接口返回500刷新token后,你递归调用了
signInData()但没有加return,递归执行拿到的请求结果会被直接丢弃,就算刷新token后请求成功也拿不到数据。 - 重复解析响应:dio默认会自动将json格式的响应体转成Map类型,你额外调用
jsonDecode(response.data.toString())属于重复解析,在部分响应格式场景下会直接抛异常,导致Future进入error状态但你没做错误日志捕获。
修复方案
推荐用第一种方案,逻辑更简单,避免重复请求。
方案1:请求完成拿到数据后再跳转,通过路由参数传值
第一步:调整signInData方法逻辑,先拿数据再跳转
Future<CarDetails?> signInData() async { final prefs = await SharedPreferences.getInstance(); final String? token = prefs.getString('token'); 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", })); print("接口返回:${response.data},状态码:${response.statusCode}"); if (response.statusCode == 200) { // 先解析数据 CarDetails carData = CarDetails.fromJson(response.data); // 校验组件挂载状态再跳转,避免内存泄漏 if(mounted){ Navigator.of(context).pushReplacement( MaterialPageRoute( builder: (context) => ResultsPage(carDetail: carData), ), ); } return carData; } else if (response.statusCode == 500) { await getToken(); // 加return,把递归请求的结果返回 return signInData(); } // 其他状态码直接抛异常 throw Exception("请求失败,状态码${response.statusCode}"); } catch (e) { print("请求异常:$e"); rethrow; } }
第二步:修改ResultsPage,接收路由参数直接渲染
class ResultsPage extends StatefulWidget { final CarDetails carDetail; const ResultsPage({Key? key, required this.carDetail}) : super(key: key); @override _ResultsPageState createState() => _ResultsPageState(); } class _ResultsPageState extends State<ResultsPage> { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(), body: Center( child: Text(widget.carDetail.make ?? "未获取到车辆厂商信息"), ), ); } }
方案2:在结果页发起请求(不推荐)
如果要把请求逻辑放在结果页,首先要删掉signInData方法里200状态码下的跳转逻辑,其次不要把请求方法写在State子类里(State类和组件生命周期绑定,独立实例化会丢context和状态),把网络请求抽离到独立的服务类中,再在结果页初始化实例发起请求:
// 结果页initState修正示例 @override void initState() { super.initState(); // 替换为你自己的请求服务类实例 final api = ApiService(); objectList = api.signInData(); }
注意:不要在
build方法里初始化Future,否则每一次组件重绘都会重新发起请求,浪费流量和性能。
内容的提问来源于stack exchange,提问作者SaDev
相关产品推荐
相关产品推荐

