Flutter initState调用async请求时await未生效build提前触发问题求助
问题原因
getBungalows是异步方法,await仅会暂停该异步方法内部的后续逻辑,不会阻塞外部代码执行。initState调用该方法后不会等待网络请求完成就会执行完毕,Flutter框架随后就会触发build方法渲染页面,因此控制台先打印done build,等网络请求返回后才会执行await后的代码打印done,属于异步逻辑的正常表现,不是bug。- 现有代码还存在几个明显问题:
- 重写
initState方法没有调用super.initState(),不符合State生命周期的规范要求 - 声明的
late List<Bungalow> bungalows在异步请求完成赋值前如果被访问,会抛出LateInitializationError异常 - 拿到接口返回数据后没有调用
setState更新状态,页面不会触发重新渲染,数据就算请求成功也无法展示到界面上
- 重写
修正方案
按照下方代码修改HomeScreen逻辑即可,新增加载态、错误态判断,请求完成后调用setState刷新页面:
class _HomeScreenState extends State<HomeScreen> { HttpService httpService = HttpService(); List<Bungalow>? bungalows; // 改为可空类型,避免未初始化访问报错 bool isLoading = true; // 加载状态标识 String? errorMsg; // 存储错误信息 bool isLoggedIn = false; User? user; void getBungalows() async { try { bungalows = await httpService.getBungalows(); errorMsg = null; } catch (e) { errorMsg = e.toString(); } finally { // 增加mounted判断,避免页面销毁后调用setState引发异常 if (mounted) { setState(() { isLoading = false; }); } print('done'); } } @override Widget build(BuildContext context) { if (widget.user != null) { isLoggedIn = true; user = widget.user; } print('done build'); return Scaffold( backgroundColor: Colors.white, body: Column( children: [ Text(isLoggedIn ? user!.userDetail.username : 'No login'), // 按状态展示对应内容 if (isLoading) const CircularProgressIndicator() else if (errorMsg != null) Text('加载失败:$errorMsg') else Expanded( child: ListView.builder( itemCount: bungalows?.length ?? 0, itemBuilder: (context, index) { final bungalow = bungalows![index]; return ListTile( title: Text(bungalow.address), // 可自行扩展其他别墅信息展示逻辑 ); }, ), ) ], ), ); } @override void initState() { super.initState(); // 补上父类方法调用,强制要求 getBungalows(); } }
内容的提问来源于stack exchange,提问作者Indusara Umayanga
相关产品推荐
相关产品推荐

