Flutter Web中Future执行then回调后_textInfo变量未更新问题
问题根因
- 核心错误是
setState作用域不符合异步逻辑的执行时序:setState仅会同步执行传入闭包内的代码,执行完成后触发一次界面重绘。你写在postOrder().then()里的_textInfo赋值属于异步回调逻辑,等接口返回200状态码触发回调时,早就脱离了这次setState的执行上下文。实际上_textInfo已经被成功赋值,但这次赋值没有包裹在setState的闭包中,Flutter感知不到状态变化、不会触发界面重绘,所以Text组件始终显示初始旧文案,看起来就像变量没有被更新。 - 你在
setState闭包末尾同步执行了myb.clear(),循环发起postOrder的逻辑是同步跑完的,等异步接口真正返回时,购物车列表已经被清空,很容易出现请求参数取值异常,也不符合“提交成功后再清空购物车”的正常交互逻辑。 - 当前写法下多个并发的postOrder请求返回时会反复覆盖
_textInfo,最终只会显示最后一个返回请求的结果,无法实现“所有订单提交完成后统一提示”的效果。
修复方案
- 异步回调中修改需要同步到界面的状态时,必须把修改逻辑包裹在
setState闭包内,主动触发界面重绘。单个请求返回后即时更新提示的写法如下:
postOrder( widget.basketId, Session.sessionQRCode, "Pas Membre", "Especes", Session.sessionEstaName, myb[i].price, myb[i].product, myb[i].add ).then((value) { // 回调内修改状态必须包裹setState setState(() { _textInfo= 'ORDER : $value'; }); });
- 不要在发起异步请求的同步代码块里直接清空购物车,等所有请求执行完成后再执行清空操作。如果需要等全部订单提交成功后再统一展示提示,可以用
Future.wait收集所有异步请求,待全部完成后再更新状态,参考代码如下:
Container( padding: const EdgeInsets.all(Pages.edgeInsetsAll), child: ElevatedButton( onPressed: () async { List<Future> orderRequestList = []; // 遍历购物车收集所有订单请求 for (int i = 0; i < myb.length; i++) { int orderCount = myb[i].count > 1 ? myb[i].count : 1; for (int j = 0; j < orderCount; j++) { orderRequestList.add(postOrder( widget.basketId, Session.sessionQRCode, "Pas Membre", "Especes", Session.sessionEstaName, myb[i].price, myb[i].product, myb[i].add )); } } // 等待所有订单请求返回结果 List orderResults = await Future.wait(orderRequestList); // 所有请求完成后统一更新UI、清空购物车 setState(() { _textInfo = '订单提交成功,共提交${orderResults.length}件商品'; myb.clear(); }); }, child: Text(_textInfo) ), )
内容的提问来源于stack exchange,提问作者user18262850
相关产品推荐
相关产品推荐

