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

Flutter实现最多2个并发倒计时按钮的需求求助

多按钮倒计时限流实现(最多2个同时运行)

需求说明

有10个按钮,点击按钮后从0开始倒计时至60秒;最多允许2个按钮同时执行倒计时,其余点击的按钮进入等待队列;当正在运行的任意一个倒计时完成后,自动启动队列中的下一个按钮开始倒计时。

用户尝试的初始代码

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  List<int> buttonCounts = List<int>.filled(10, 0);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Button Counter'),
        ),
        body: ListView.builder(
          itemCount: buttonCounts.length,
          itemBuilder: (context, index) {
            return ListTile(
              title: Text('Button ${index + 1}'),
              subtitle: Text('Count: ${buttonCounts[index]}'),
              trailing: ElevatedButton(
                child: Text('Tap'),
                onPressed: () {
                  if (buttonCounts[index] < 60) {
                    incrementCounter(index);
                  }
                },
              ),
            );
          },
        ),
      ),
    );
  }

  void incrementCounter(int index) async {
    while (buttonCounts[index] < 60) {
      // Delay for 1 second before incrementing the counter
      await Future.delayed(Duration(seconds: 1));
      setState(() {
        buttonCounts[index]++;
      });
    }
  }
}

用户后续尝试的代码(未解决问题)

void startCounting(int index) async {
  isButtonRunning[index] = true;
  setState(() {});

  await Future.delayed(Duration(seconds: 1));

  while (buttonCounts[index] < 60) {
    await Future.delayed(Duration(seconds: 1));
    setState(() {
      buttonCounts[index]++;
    });
  }

  isButtonRunning[index] = false;

  if (index < 2) {
    if (isButtonRunning[2]) {
      startCounting(3);
    }
    if (isButtonRunning[3]) {
      startCounting(2);
    }
  }
}

解决方案代码

import 'package:flutter/material.dart';
import 'dart:collection';

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  // 存储每个按钮的倒计时数值
  List<int> buttonCounts = List<int>.filled(10, 0);
  // 标记按钮是否正在处理中(运行或等待)
  List<bool> isProcessing = List<bool>.filled(10, false);
  // 正在运行的按钮索引列表(最多2个)
  List<int> runningQueue = [];
  // 等待队列(先进先出)
  Queue<int> waitingQueue = Queue();

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: const Text('Button Counter'),
        ),
        body: ListView.builder(
          itemCount: buttonCounts.length,
          itemBuilder: (context, index) {
            return ListTile(
              title: Text('Button ${index + 1}'),
              subtitle: Text(
                isProcessing[index]
                    ? (runningQueue.contains(index)
                        ? 'Count: ${buttonCounts[index]}'
                        : 'Waiting...')
                    : 'Idle',
              ),
              trailing: ElevatedButton(
                child: const Text('Tap'),
                onPressed: isProcessing[index] ? null : () => handleButtonTap(index),
              ),
            );
          },
        ),
      ),
    );
  }

  void handleButtonTap(int index) {
    setState(() {
      isProcessing[index] = true;
    });

    // 运行队列未满,直接启动倒计时
    if (runningQueue.length < 2) {
      startCountdown(index);
    } else {
      // 加入等待队列
      waitingQueue.add(index);
    }
  }

  void startCountdown(int index) async {
    runningQueue.add(index);
    setState(() {
      buttonCounts[index] = 0;
    });

    // 倒计时循环
    while (buttonCounts[index] < 60) {
      await Future.delayed(const Duration(seconds: 1));
      setState(() {
        buttonCounts[index]++;
      });
    }

    // 倒计时完成,清理状态
    runningQueue.remove(index);
    setState(() {
      isProcessing[index] = false;
    });

    // 启动等待队列中的下一个按钮
    if (waitingQueue.isNotEmpty) {
      int nextIndex = waitingQueue.removeFirst();
      startCountdown(nextIndex);
    }
  }
}

关键逻辑说明

  • 状态标记:用isProcessing防止按钮重复点击,同时区分按钮是处于运行还是等待状态;buttonCounts记录每个按钮的当前倒计时数值。
  • 队列控制:runningQueue限制最多2个运行中的按钮,waitingQueue用队列保证等待按钮的先进先出顺序。
  • 触发逻辑:按钮点击时判断运行队列容量,未满则直接启动,否则进入等待;每个倒计时完成后自动检查等待队列,启动下一个任务。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 19:05:36