Flutter登录时展示CircularProgressIndicator阻塞UI问题如何解决
问题根因
你的判断完全正确:Dart中的sleep()是同步阻塞方法,会直接卡住Flutter的UI主线程,所有UI重绘操作都会等到阻塞结束后才会批量执行,所以你两次setState的状态变更会被合并,最终看不到加载态的切换效果,甚至会导致进度条卡顿。
正确修改方案
只需要修改_handleLogin方法,用Dart的异步语法async/await配合Future.delayed实现非阻塞等待即可,具体改动如下:
- 给
_handleLogin方法添加async关键字,返回值改为Future<void> - 把阻塞的
sleep()替换为await Future.delayed()实现非阻塞等待
修改后完整代码:
// 注意方法签名新增了 async 关键字,返回值改为Future<void> Future<void> _handleLogin() async { setState(() { _isLoggingIn = true; }); print("Start Logging In"); // 替换sleep为Future.delayed,前面加await实现非阻塞等待 await Future.delayed(const Duration(seconds: 3)); print("Stop Logging In"); setState(() { _isLoggingIn = false; }); }
按钮的onPressed回调不需要任何修改,可以直接调用异步的_handleLogin方法。
改动说明
- 方法末尾的
async关键字是Dart异步方法的标识,只有标记了async的方法内部才能使用await关键字 Future.delayed是Dart提供的异步等待API,等待过程不会阻塞主线程,UI可以正常响应和重绘,所以第一个setState设置的加载状态会立刻生效,进度条也可以正常转动await关键字会让后续代码暂停执行,直到Future.delayed的等待时间结束,再往下执行关闭加载状态的逻辑,完全符合模拟网络请求等待的需求。
内容的提问来源于stack exchange,提问作者Samaranth
相关产品推荐
相关产品推荐

