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

Flutter实现提交后禁用按钮,直至新问题加载且不提前重建页面

解决Flutter测验页面提交按钮禁用问题

核心问题分析

原代码存在两个关键问题:

  • 每次build调用getQuestion(),导致页面重建时重复发起请求,且无法通过普通状态变量控制按钮禁用(因为setState会触发提前加载新问题)
  • 提交后无法精准控制按钮禁用状态,直到新问题完全加载完成

解决方案

1. 重构Future管理,避免重复请求

将getQuestion()的结果存储为状态变量,仅在初始化或提交答案后主动更新,而非在build中直接调用,防止不必要的重复请求。

2. 用状态变量控制按钮禁用

添加_isSubmitting变量标记提交状态,点击提交后立即设为true禁用按钮,待新问题加载完成后再设为false恢复可用。

完整修改代码

import 'package:flutter/material.dart';

class QuizForm extends StatefulWidget {
  const QuizForm({Key? key}) : super(key: key);

  @override
  State<QuizForm> createState() => _QuizFormState();
}

class _QuizFormState extends State<QuizForm> {
  int buildCount = 0;
  late Future _questionFuture;
  bool _isSubmitting = false;

  // 模拟API请求获取题目
  Future getQuestion() async {
    // 替换为实际API请求逻辑
    await Future.delayed(const Duration(seconds: 1));
    return "新题目数据";
  }

  @override
  void initState() {
    super.initState();
    // 初始化时加载第一个题目
    _questionFuture = getQuestion();
  }

  @override
  Widget build(BuildContext context) {
    print(buildCount);
    print('UI正在构建');
    return SafeArea(
      child: Scaffold(
        body: FutureBuilder(
          future: _questionFuture,
          builder: (context, snapshot) {
            // 题目加载完成后重置提交状态
            if (snapshot.connectionState == ConnectionState.done && _isSubmitting) {
              setState(() {
                _isSubmitting = false;
              });
            }

            // 处理加载状态
            if (snapshot.connectionState == ConnectionState.waiting) {
              return const Center(child: CircularProgressIndicator());
            }

            return ListView(
              children: [
                const ListTile(title: Text('Quiz Title')),
                const ListTile(title: Text('1')),
                const ListTile(title: Text('2')),
                const ListTile(title: Text('3')),
                const ListTile(title: Text('4')),
                const SizedBox(height: 20),
                ElevatedButton(
                  onPressed: _isSubmitting
                      ? null
                      : () async {
                          print('正在保存答案,请等待');
                          // 标记提交状态,禁用按钮
                          setState(() {
                            _isSubmitting = true;
                          });

                          // 模拟保存答案的API请求
                          await Future.delayed(const Duration(seconds: 3));
                          buildCount++;

                          // 更新题目Future,触发FutureBuilder加载新题目
                          setState(() {
                            _questionFuture = getQuestion();
                          });
                        },
                  child: const Text('提交测验'),
                )
              ],
            );
          },
        ),
      ),
    );
  }
}

关键修改点说明

  • _questionFuture变量:存储题目请求的Future,仅在初始化和提交后更新,避免build时重复发起请求
  • _isSubmitting状态:点击提交后立即设为true禁用按钮,待新题目加载完成(snapshot.connectionState == ConnectionState.done)后自动重置为false
  • FutureBuilder状态处理:在builder中判断题目加载状态,显示加载指示器,同时处理提交状态的重置

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 13:50:41