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
相关产品推荐
相关产品推荐

