flutter按钮防止多次点击
1.防抖(debounce)
防抖可以概括为触发高频事件后n秒内函数只会执行一次,如果n秒内高频事件再次被触发,则重新计算时间。
如果某一事件被连续快速地触发多次,只会执行最后那一次。
示例代码
import 'package:flutter/material.dart';
import 'dart:async';
typedef DebounceCallback = Future<void> Function();
class Debounce {
final Duration duration;
Timer? _timer;
Debounce(this.duration);
void call(DebounceCallback callback) {
_timer?.cancel();
_timer = Timer(duration, () async {
await callback();
});
}
}
class DebouncedButtonApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('Debounce Button Example')),
body: Center(child: DebouncedButton()),
),
);
}
}
class DebouncedButton extends StatefulWidget {
@override
_DebouncedButtonState createState() => _DebouncedButtonState();
}
class _DebouncedButtonState extends State<DebouncedButton> {
final Debounce _debounce = Debounce(Duration(milliseconds: 500));
Future<void> _handleButtonClick() async {
// 这里是按钮点击后执行的操作
print('Button clicked at ${DateTime.now()}');
await Future.delayed(Duration(milliseconds: 200)); // 模拟一些异步操作
}
@override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: () => _debounce(() => _handleButtonClick()),
child: Text('Click Me'),
);
}
}
void main() {
runApp(DebouncedButtonApp());
}
2.节流(throttle)
节流就是减少流量,将频繁触发的事件减少。n 秒内只运行一次,若在n秒内重复触发,只有一次生效。如限制1s,则1s内只执行一次。
示例代码
import 'package:flutter/material.dart';
import 'dart:async';
typedef ThrottleCallback = Future<void> Function();
class Throttle {
final Duration duration;
int _lastEventTimestamp = 0;
bool _isWaiting = false;
Throttle(this.duration);
Future<void> start(ThrottleCallback callback) async {
final now = DateTime.now().millisecondsSinceEpoch;
if (_lastEventTimestamp == 0 ||
now - _lastEventTimestamp >= duration.inMilliseconds) {
_lastEventTimestamp = now;
if (!_isWaiting) {
_isWaiting = true;
await callback();
_isWaiting = false;
}
} else {
// 事件在限流时间内,忽略此次事件
}
}
}
class ThrottledButtonApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('Throttle Button Example')),
body: Center(child: ThrottledButton()),
),
);
}
}
class ThrottledButton extends StatefulWidget {
@override
_ThrottledButtonState createState() => _ThrottledButtonState();
}
class _ThrottledButtonState extends State<ThrottledButton> {
final Throttle _throttle = Throttle(Duration(milliseconds: 500));
Future<void> _handleButtonClick() async {
// 这里是按钮点击后执行的操作
print('Button clicked at ${DateTime.now()}');
await Future.delayed(Duration(milliseconds: 200)); // 模拟一些异步操作
}
@override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: () => _throttle.start(_handleButtonClick),
child: Text('Click Me'),
);
}
}
void main() {
runApp(ThrottledButtonApp());
}