You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 12:15:05