Flutter Stateful Widget中按钮无法在异步请求完成前禁用问题
问题根源
- 你使用了
dart:io包下的sleep方法模拟请求,该方法是同步阻塞API,会直接卡住Flutter主渲染线程。setState触发的重绘操作需要等待主线程空闲时才会执行,因此会出现阻塞结束后才更新按钮状态的现象。 - 你将
_acceptRequest、_sendRequest两个业务方法定义在build函数内部,属于不规范写法,每次组件重绘都会重复生成方法实例。 - 缺少请求结束后恢复按钮可用状态的逻辑。
修复方案
把同步阻塞的sleep替换为异步非阻塞的Future.delayed模拟请求,同时将业务方法迁移到State类内部,补充请求结束后的状态重置逻辑,修正后代码如下:
import 'package:flutter/material.dart'; class StatefulButtonDisable extends StatefulWidget { const StatefulButtonDisable({Key? key}) : super(key: key); @override _StatefulButtonDisableState createState() => _StatefulButtonDisableState(); } class _StatefulButtonDisableState extends State<StatefulButtonDisable> { bool _enableButton = true; Future<bool> _acceptRequest(id) async { print('accepting request $id'); // 用异步延迟替代同步sleep,不会阻塞主线程 await Future.delayed(const Duration(seconds: 5)); return true; } _sendRequest(id) async { setState(() { _enableButton = false; }); await _acceptRequest(id); // 请求完成后恢复按钮可用状态 setState(() { _enableButton = true; }); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Disable Button'), ), body: Container( child: ElevatedButton( onPressed: _enableButton ? () { _sendRequest(7); } : null, child: const Text('Press Me'), ), ), ); } }
内容的提问来源于stack exchange,提问作者OptimusPrime
相关产品推荐
相关产品推荐

