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

Flutter FutureBuilder调用setState报错修复后TextFormField无法点击问题

问题根因与修复方案

存在的4个核心问题

  • 按钮状态逻辑写反:需求是「请求有返回数据时禁用按钮」,你的代码在snapshot.hasData时将_isButtonDisabled设为false,逻辑完全颠倒,这是按钮始终启用的直接原因。
  • 触发无限重绘死循环:FutureBuilder的builder方法会在组件每次重绘时执行,你在builder内每次都通过addPostFrameCallback插入setState操作,setState又会触发组件重绘,往复循环导致UI卡顿、交互无响应,这是TextFormField无法点击的核心原因。
  • 数据展示逻辑错误:有返回数据时你清空了_timeController,仅用hintText展示接口返回值,hintText是无输入内容时的提示文本,不符合正式数据展示的场景。
  • 接口重复请求:你直接将getTimes(selectedDate)作为future参数传入FutureBuilder,每次组件重绘都会重新调用接口,即使用户选中的日期没有变化也会重复请求。

修复方案

第一步:缓存接口请求Future

在你的State类中新增一个变量缓存请求,仅当选中的日期变化时才重新发起请求:

// 类属性定义
Future<double?>? _timesFuture;

// DateTimePicker选中日期的回调方法中更新请求
void onSelectDate(DateTime pickedDate) {
  setState(() {
    selectedDate = pickedDate;
    // 仅日期变化时重新生成请求Future
    _timesFuture = getTimes(pickedDate);
  });
}

第二步:移除builder内的状态更新逻辑

不需要单独维护_isButtonDisabled变量,直接通过snapshot的状态同步控制按钮和输入框状态即可,避免在build过程中修改状态:

child: FutureBuilder<double?>(
  future: _timesFuture,
  builder: (BuildContext context, AsyncSnapshot<double> snapshot) {
    // 提前判断是否有有效返回数据
    final hasValidData = snapshot.hasData && snapshot.data != null;
    // 有数据时直接给controller赋值,不要用hintText存业务数据
    if (hasValidData) {
      _timeController.text = '${snapshot.data} h';
    } else if(!snapshot.hasData && _timeController.text.endsWith(' h')) {
      // 无数据时清空之前的接口返回值
      _timeController.clear();
    }

    return TextFormField(
      controller: _timeController,
      textAlign: TextAlign.center,
      // 有数据时禁用输入框
      enabled: !hasValidData,
      decoration: InputDecoration(
        hintText: "0 h",
        contentPadding: EdgeInsets.zero,
        filled: true,
        // 有数据时用浅色背景标识禁用状态
        fillColor: hasValidData ? Colors.white70 : Colors.white,
      ),
    );
  }
)

第三步:按钮状态直接同步请求状态

按钮的onPressed参数直接根据snapshot状态控制,不需要额外维护布尔变量:

// 你的按钮控件写法示例
ElevatedButton(
  // 有返回数据时禁用按钮,无数据时启用,完全匹配需求
  onPressed: snapshot.hasData && snapshot.data != null ? null : () {
    // 按钮点击逻辑
  },
  child: Text('提交'),
)

如果你一定要保留_isButtonDisabled变量,只需要在onSelectDate发起请求、以及请求结束的回调里修改状态即可,不要在builder中操作。


内容的提问来源于stack exchange,提问作者JS1

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 10:36:04