Dart Timer 全面总结指南
目录
Timer基础概念
什么是Timer?
Timer是Dart中用于执行延迟任务和周期性任务的核心类。它基于事件循环机制,允许开发者在指定的时间后执行代码或重复执行某个任务。
导入Timer
dart
import 'dart:async';
Timer的基本特性
- 异步执行:Timer不会阻塞当前线程
- 事件循环驱动:基于Dart的事件循环机制
- 可取消:可以在执行前取消Timer
- 高精度:支持微秒级别的时间控制
Timer核心API
1. 构造函数
Timer(Duration duration, void Function() callback)
创建一个一次性Timer,在指定时间后执行回调函数。
dart
Timer timer = Timer(Duration(seconds: 3), () {
print('3秒后执行');
});
Timer.periodic(Duration period, void Function(Timer) callback)
创建一个周期性Timer,每隔指定时间执行一次回调函数。
dart
Timer periodicTimer = Timer.periodic(Duration(seconds: 1), (timer) {
print('每秒执行一次,已执行${timer.tick}次');
});
Timer.run(void Function() callback)
立即异步执行回调函数(等同于Timer(Duration.zero, callback))。
dart
Timer.run(() {
print('立即异步执行');
});
2. 核心属性和方法
属性
bool isActive
:Timer是否处于活动状态int tick
:周期性Timer的执行次数(仅对periodic timer有效)
方法
void cancel()
:取消Timerstatic void run(void Function() callback)
:静态方法,立即异步执行
Timer类型详解
1. 一次性Timer(One-shot Timer)
一次性Timer在指定延迟后执行一次,然后自动销毁。
dart
void demonstrateOneShotTimer() {
print('开始计时...');
Timer(Duration(milliseconds: 500), () {
print('500毫秒后执行');
});
Timer(Duration(seconds: 2), () {
print('2秒后执行');
});
}
2. 周期性Timer(Periodic Timer)
周期性Timer按照指定间隔重复执行,直到被手动取消。
dart
void demonstratePeriodicTimer() {
int counter = 0;
Timer periodicTimer = Timer.periodic(Duration(seconds: 1), (timer) {
counter++;
print('执行第${counter}次,tick: ${timer.tick}');
// 执行5次后停止
if (counter >= 5) {
timer.cancel();
print('Timer已取消');
}
});
}
3. 立即执行Timer
使用Timer.run()或Duration.zero创建立即执行的异步任务。
dart
void demonstrateImmediateTimer() {
print('同步代码1');
Timer.run(() {
print('立即异步执行');
});
Timer(Duration.zero, () {
print('零延迟异步执行');
});
print('同步代码2');
}
// 输出顺序:同步代码1 -> 同步代码2 -> 立即异步执行 -> 零延迟异步执行
实用示例代码
1. 倒计时器
dart
class CountdownTimer {
Timer? _timer;
int _currentSeconds;
final int _initialSeconds;
final void Function(int) onTick;
final void Function() onFinished;
CountdownTimer({
required int seconds,
required this.onTick,
required this.onFinished,
}) : _initialSeconds = seconds, _currentSeconds = seconds;
void start() {
_timer?.cancel(); // 取消之前的timer
_currentSeconds = _initialSeconds;
_timer = Timer.periodic(Duration(seconds: 1), (timer) {
if (_currentSeconds > 0) {
onTick(_currentSeconds);
_currentSeconds--;
} else {
timer.cancel();
onFinished();
}
});
}
void pause() {
_timer?.cancel();
}
void reset() {
_timer?.cancel();
_currentSeconds = _initialSeconds;
}
void dispose() {
_timer?.cancel();
}
bool get isActive => _timer?.isActive ?? false;
int get remainingSeconds => _currentSeconds;
}
// 使用示例
void useCountdownTimer() {
final countdown = CountdownTimer(
seconds: 10,
onTick: (seconds) => print('剩余时间: ${seconds}秒'),
onFinished: () => print('倒计时结束!'),
);
countdown.start();
}
2. 防抖(Debounce)实现
dart
class Debouncer {
Timer? _timer;
final Duration delay;
Debouncer({required this.delay});
void call(void Function() action) {
_timer?.cancel();
_timer = Timer(delay, action);
}
void dispose() {
_timer?.cancel();
}
}
// 使用示例
void demonstrateDebounce() {
final debouncer = Debouncer(delay: Duration(milliseconds: 500));
// 模拟用户快速输入
for (int i = 0; i < 5; i++) {
Timer(Duration(milliseconds: i * 100), () {
print('用户输入: $i');
debouncer(() {
print('执行搜索操作,最终输入: $i');
});
});
}
}
3. 节流(Throttle)实现
dart
class Throttler {
Timer? _timer;
final Duration duration;
bool _isThrottled = false;
Throttler({required this.duration});
void call(void Function() action) {
if (!_isThrottled) {
action();
_isThrottled = true;
_timer = Timer(duration, () {
_isThrottled = false;
});
}
}
void dispose() {
_timer?.cancel();
}
}
// 使用示例
void demonstrateThrottle() {
final throttler = Throttler(duration: Duration(seconds: 1));
// 模拟频繁调用
for (int i = 0; i < 10; i++) {
Timer(Duration(milliseconds: i * 200), () {
throttler(() {
print('节流执行: $i');
});
});
}
}
4. 重试机制
dart
class RetryTimer {
static Future<T> retry<T>(
Future<T> Function() operation, {
int maxAttempts = 3,
Duration delay = const Duration(seconds: 1),
Duration? backoffMultiplier,
}) async {
int attempts = 0;
Duration currentDelay = delay;
while (attempts < maxAttempts) {
try {
attempts++;
print('尝试第${attempts}次...');
return await operation();
} catch (e) {
if (attempts >= maxAttempts) {
print('达到最大重试次数,操作失败');
rethrow;
}
print('第${attempts}次尝试失败: $e');
print('等待${currentDelay.inMilliseconds}ms后重试...');
await Future.delayed(currentDelay);
if (backoffMultiplier != null) {
currentDelay = Duration(
milliseconds: (currentDelay.inMilliseconds *
(backoffMultiplier.inMilliseconds / 1000)).round()
);
}
}
}
throw Exception('重试失败');
}
}
// 使用示例
Future<void> demonstrateRetry() async {
try {
await RetryTimer.retry(
() async {
// 模拟可能失败的网络请求
if (DateTime.now().millisecondsSinceEpoch % 3 != 0) {
throw Exception('网络错误');
}
return '请求成功';
},
maxAttempts: 3,
delay: Duration(seconds: 1),
backoffMultiplier: Duration(milliseconds: 2000), // 2x退避
);
} catch (e) {
print('最终失败: $e');
}
}
5. 心跳检测
dart
class HeartbeatMonitor {
Timer? _heartbeatTimer;
Timer? _timeoutTimer;
final Duration interval;
final Duration timeout;
final void Function() onHeartbeat;
final void Function() onTimeout;
HeartbeatMonitor({
required this.interval,
required this.timeout,
required this.onHeartbeat,
required this.onTimeout,
});
void start() {
_startHeartbeat();
}
void _startHeartbeat() {
_heartbeatTimer?.cancel();
_heartbeatTimer = Timer.periodic(interval, (timer) {
onHeartbeat();
_startTimeoutTimer();
});
}
void _startTimeoutTimer() {
_timeoutTimer?.cancel();
_timeoutTimer = Timer(timeout, () {
onTimeout();
stop();
});
}
void receivePong() {
_timeoutTimer?.cancel();
}
void stop() {
_heartbeatTimer?.cancel();
_timeoutTimer?.cancel();
}
bool get isActive => _heartbeatTimer?.isActive ?? false;
}
// 使用示例
void demonstrateHeartbeat() {
final monitor = HeartbeatMonitor(
interval: Duration(seconds: 5),
timeout: Duration(seconds: 10),
onHeartbeat: () => print('发送心跳包'),
onTimeout: () => print('连接超时'),
);
monitor.start();
// 模拟接收到pong响应
Timer(Duration(seconds: 3), () {
monitor.receivePong();
print('收到pong响应');
});
}
高级用法和技巧
1. Timer链式调用
dart
class TimerChain {
final List<({Duration delay, void Function() action})> _chain = [];
Timer? _currentTimer;
int _currentIndex = 0;
TimerChain add(Duration delay, void Function() action) {
_chain.add((delay: delay, action: action));
return this;
}
void execute() {
_currentIndex = 0;
_executeNext();
}
void _executeNext() {
if (_currentIndex >= _chain.length) return;
final current = _chain[_currentIndex];
_currentTimer = Timer(current.delay, () {
current.action();
_currentIndex++;
_executeNext();
});
}
void cancel() {
_currentTimer?.cancel();
}
}
// 使用示例
void demonstrateTimerChain() {
TimerChain()
.add(Duration(seconds: 1), () => print('第1步'))
.add(Duration(milliseconds: 500), () => print('第2步'))
.add(Duration(seconds: 2), () => print('第3步'))
.execute();
}
2. Timer池管理
dart
class TimerPool {
final Map<String, Timer> _timers = {};
void addTimer(String id, Duration duration, void Function() callback) {
cancelTimer(id); // 取消同ID的现有timer
_timers[id] = Timer(duration, () {
callback();
_timers.remove(id);
});
}
void addPeriodicTimer(String id, Duration period, void Function(Timer) callback) {
cancelTimer(id);
_timers[id] = Timer.periodic(period, callback);
}
void cancelTimer(String id) {
_timers[id]?.cancel();
_timers.remove(id);
}
void cancelAll() {
_timers.values.forEach((timer) => timer.cancel());
_timers.clear();
}
bool hasTimer(String id) => _timers.containsKey(id);
int get activeTimerCount => _timers.length;
List<String> get activeTimerIds => _timers.keys.toList();
}
// 使用示例
void demonstrateTimerPool() {
final pool = TimerPool();
pool.addTimer('task1', Duration(seconds: 2), () => print('任务1完成'));
pool.addPeriodicTimer('heartbeat', Duration(seconds: 1), (timer) {
print('心跳 ${timer.tick}');
if (timer.tick >= 5) {
pool.cancelTimer('heartbeat');
}
});
print('活跃Timer数量: ${pool.activeTimerCount}');
print('活跃Timer ID: ${pool.activeTimerIds}');
}
最佳实践
1. 资源管理
dart
class TimerManager {
final List<Timer> _timers = [];
Timer createTimer(Duration duration, void Function() callback) {
final timer = Timer(duration, () {
callback();
_timers.remove(timer);
});
_timers.add(timer);
return timer;
}
Timer createPeriodicTimer(Duration period, void Function(Timer) callback) {
final timer = Timer.periodic(period, callback);
_timers.add(timer);
return timer;
}
void dispose() {
for (final timer in _timers) {
timer.cancel();
}
_timers.clear();
}
}
2. 错误处理
dart
void safeTimerExecution() {
Timer(Duration(seconds: 1), () {
try {
// 可能抛出异常的代码
throw Exception('示例异常');
} catch (e, stackTrace) {
print('Timer执行出错: $e');
print('堆栈跟踪: $stackTrace');
}
});
}
3. 内存泄漏预防
dart
class Widget {
Timer? _timer;
void startTimer() {
// 确保之前的timer被取消
_timer?.cancel();
_timer = Timer.periodic(Duration(seconds: 1), (timer) {
// 定期任务
});
}
void dispose() {
// 在组件销毁时取消timer
_timer?.cancel();
_timer = null;
}
}
常见问题和解决方案
1. Timer不执行的问题
dart
// ❌ 错误:主线程阻塞
void blockingCode() {
Timer(Duration(seconds: 1), () => print('不会执行'));
// 阻塞主线程
while(true) {
// 死循环阻塞事件循环
}
}
// ✅ 正确:保持事件循环运行
void nonBlockingCode() {
Timer(Duration(seconds: 1), () => print('会正常执行'));
// 使用异步操作代替阻塞
Timer.periodic(Duration(milliseconds: 100), (timer) {
// 定期检查条件
if (shouldStop) {
timer.cancel();
}
});
}
2. Timer精度问题
dart
void timerAccuracy() {
final stopwatch = Stopwatch()..start();
Timer(Duration(milliseconds: 100), () {
stopwatch.stop();
print('预期: 100ms, 实际: ${stopwatch.elapsedMilliseconds}ms');
// 实际时间可能略大于预期时间
});
}
3. 周期性Timer的tick计数
dart
void periodicTimerTicks() {
Timer.periodic(Duration(seconds: 1), (timer) {
print('Tick: ${timer.tick}'); // 从1开始计数
if (timer.tick >= 5) {
timer.cancel();
}
});
}
性能优化建议
1. 避免创建过多Timer
dart
// ❌ 避免:为每个任务创建独立timer
class BadExample {
void scheduleMultipleTasks() {
for (int i = 0; i < 100; i++) {
Timer(Duration(milliseconds: i * 10), () {
processTask(i);
});
}
}
}
// ✅ 推荐:使用单个timer处理多个任务
class GoodExample {
final List<({DateTime when, void Function() task})> _scheduledTasks = [];
Timer? _processingTimer;
void scheduleTask(Duration delay, void Function() task) {
_scheduledTasks.add((
when: DateTime.now().add(delay),
task: task,
));
_startProcessingIfNeeded();
}
void _startProcessingIfNeeded() {
if (_processingTimer?.isActive == true) return;
_processingTimer = Timer.periodic(Duration(milliseconds: 10), (timer) {
final now = DateTime.now();
final readyTasks = _scheduledTasks.where((item) =>
now.isAfter(item.when)).toList();
for (final taskItem in readyTasks) {
taskItem.task();
_scheduledTasks.remove(taskItem);
}
if (_scheduledTasks.isEmpty) {
timer.cancel();
}
});
}
}
2. 合理选择Timer类型
dart
// 立即执行用Timer.run()
Timer.run(() => print('立即执行'));
// 短延迟用Timer
Timer(Duration(milliseconds: 100), () => print('短延迟'));
// 周期性任务用Timer.periodic
Timer.periodic(Duration(seconds: 1), (timer) => print('周期性'));
3. 及时取消不需要的Timer
dart
class TimerLifecycleManager {
final Set<Timer> _activeTimers = {};
Timer createManagedTimer(Duration duration, void Function() callback) {
final timer = Timer(duration, () {
callback();
_activeTimers.remove(timer);
});
_activeTimers.add(timer);
return timer;
}
void cancelAllTimers() {
for (final timer in _activeTimers) {
timer.cancel();
}
_activeTimers.clear();
}
int get activeTimerCount => _activeTimers.length;
}
Future与Timer结合使用
Future.delayed与超时控制
Future.delayed是基于Timer实现的异步延迟功能,经常与timeout结合使用来控制异步操作的执行时间。
基本用法
dart
// 基础延迟操作
Future<String> delayedOperation() async {
return await Future.delayed(Duration(seconds: 2), () => "操作完成");
}
// 带超时控制的操作
Future<String> operationWithTimeout() async {
try {
return await Future.delayed(Duration(seconds: 5), () => "长时间操作")
.timeout(Duration(seconds: 3), onTimeout: () {
throw TimeoutException("操作超时", Duration(seconds: 3));
});
} catch (e) {
print('捕获异常: $e');
rethrow;
}
}
高级超时处理模式
dart
class TimeoutHandler {
/// 带重试的超时操作
static Future<T> withRetryTimeout<T>(
Future<T> Function() operation, {
Duration timeout = const Duration(seconds: 5),
int maxRetries = 3,
Duration retryDelay = const Duration(seconds: 1),
}) async {
for (int attempt = 1; attempt <= maxRetries; attempt++) {
try {
return await operation().timeout(timeout);
} on TimeoutException {
if (attempt == maxRetries) {
throw TimeoutException('操作在${maxRetries}次重试后仍然超时', timeout);
}
print('第${attempt}次尝试超时,${retryDelay.inSeconds}秒后重试...');
await Future.delayed(retryDelay);
}
}
throw Exception('不应该到达这里');
}
/// 可取消的超时操作
static Future<T> cancellableTimeout<T>(
Future<T> Function() operation, {
required Duration timeout,
required bool Function() shouldCancel,
}) async {
final completer = Completer<T>();
Timer? timeoutTimer;
Timer? checkTimer;
// 启动操作
operation().then((result) {
if (!completer.isCompleted) {
timeoutTimer?.cancel();
checkTimer?.cancel();
completer.complete(result);
}
}).catchError((error) {
if (!completer.isCompleted) {
timeoutTimer?.cancel();
checkTimer?.cancel();
completer.completeError(error);
}
});
// 设置超时
timeoutTimer = Timer(timeout, () {
if (!completer.isCompleted) {
checkTimer?.cancel();
completer.completeError(TimeoutException('操作超时', timeout));
}
});
// 定期检查取消条件
checkTimer = Timer.periodic(Duration(milliseconds: 100), (timer) {
if (shouldCancel()) {
timer.cancel();
timeoutTimer?.cancel();
if (!completer.isCompleted) {
completer.completeError(Exception('操作被取消'));
}
}
});
return completer.future;
}
}
// 使用示例
Future<void> demonstrateTimeoutHandling() async {
// 1. 带重试的超时操作
try {
final result = await TimeoutHandler.withRetryTimeout(
() => simulateNetworkRequest(),
timeout: Duration(seconds: 2),
maxRetries: 3,
);
print('操作成功: $result');
} catch (e) {
print('操作最终失败: $e');
}
// 2. 可取消的超时操作
bool cancelled = false;
Timer(Duration(seconds: 3), () => cancelled = true); // 3秒后取消
try {
final result = await TimeoutHandler.cancellableTimeout(
() => simulateLongOperation(),
timeout: Duration(seconds: 10),
shouldCancel: () => cancelled,
);
print('操作完成: $result');
} catch (e) {
print('操作被中断: $e');
}
}
Future<String> simulateNetworkRequest() async {
// 模拟网络请求,可能超时
await Future.delayed(Duration(seconds: 1 + Random().nextInt(3)));
if (Random().nextBool()) {
throw Exception('网络错误');
}
return '网络请求成功';
}
Future<String> simulateLongOperation() async {
await Future.delayed(Duration(seconds: 8));
return '长时间操作完成';
}
批量操作的超时控制
dart
class BatchOperationManager {
/// 并发执行多个操作,每个都有独立超时
static Future<List<T>> executeWithIndividualTimeouts<T>(
List<Future<T> Function()> operations,
Duration timeout,
) async {
final futures = operations.map((op) =>
op().timeout(timeout, onTimeout: () => throw TimeoutException('单个操作超时', timeout))
).toList();
final results = <T>[];
for (int i = 0; i < futures.length; i++) {
try {
results.add(await futures[i]);
} catch (e) {
print('操作${i + 1}失败: $e');
rethrow;
}
}
return results;
}
/// 整体超时控制的批量操作
static Future<List<T>> executeWithGlobalTimeout<T>(
List<Future<T> Function()> operations,
Duration globalTimeout,
) async {
return await Future.wait(
operations.map((op) => op()).toList()
).timeout(globalTimeout, onTimeout: () {
throw TimeoutException('批量操作整体超时', globalTimeout);
});
}
}
Timer与Stream的结合
dart
class TimerStreamController {
/// 创建定时数据流
static Stream<int> createTimerStream({
Duration interval = const Duration(seconds: 1),
int? maxCount,
}) {
late StreamController<int> controller;
Timer? timer;
int count = 0;
controller = StreamController<int>(
onListen: () {
timer = Timer.periodic(interval, (t) {
count++;
controller.add(count);
if (maxCount != null && count >= maxCount) {
t.cancel();
controller.close();
}
});
},
onCancel: () {
timer?.cancel();
},
);
return controller.stream;
}
/// 带超时的Stream监听
static Future<List<T>> collectWithTimeout<T>(
Stream<T> stream,
Duration timeout, {
int? maxItems,
}) async {
final completer = Completer<List<T>>();
final items = <T>[];
StreamSubscription? subscription;
Timer? timeoutTimer;
timeoutTimer = Timer(timeout, () {
subscription?.cancel();
if (!completer.isCompleted) {
completer.completeError(TimeoutException('Stream收集超时', timeout));
}
});
subscription = stream.listen(
(item) {
items.add(item);
if (maxItems != null && items.length >= maxItems) {
subscription?.cancel();
timeoutTimer?.cancel();
if (!completer.isCompleted) {
completer.complete(items);
}
}
},
onError: (error) {
subscription?.cancel();
timeoutTimer?.cancel();
if (!completer.isCompleted) {
completer.completeError(error);
}
},
onDone: () {
timeoutTimer?.cancel();
if (!completer.isCompleted) {
completer.complete(items);
}
},
);
return completer.future;
}
}
// 使用示例
Future<void> demonstrateStreamTimer() async {
// 创建定时数据流
final timerStream = TimerStreamController.createTimerStream(
interval: Duration(milliseconds: 500),
maxCount: 5,
);
try {
final items = await TimerStreamController.collectWithTimeout(
timerStream,
Duration(seconds: 3),
maxItems: 3,
);
print('收集到的数据: $items');
} catch (e) {
print('Stream处理出错: $e');
}
}
实际应用场景
1. API请求超时处理
dart
class ApiClient {
static Future<Map<String, dynamic>> request(
String url, {
Duration timeout = const Duration(seconds: 10),
}) async {
return await _performRequest(url)
.timeout(timeout, onTimeout: () {
throw TimeoutException('API请求超时: $url', timeout);
});
}
static Future<Map<String, dynamic>> _performRequest(String url) async {
// 模拟HTTP请求
await Future.delayed(Duration(seconds: 2));
return {'status': 'success', 'data': 'response data'};
}
}
2. 文件上传进度监控
dart
class FileUploadManager {
static Future<bool> uploadWithProgress(
String filePath, {
Duration timeout = const Duration(minutes: 5),
void Function(double)? onProgress,
}) async {
final completer = Completer<bool>();
Timer? progressTimer;
Timer? timeoutTimer;
double progress = 0.0;
// 模拟上传进度
progressTimer = Timer.periodic(Duration(milliseconds: 200), (timer) {
progress += 0.1;
onProgress?.call(progress);
if (progress >= 1.0) {
timer.cancel();
timeoutTimer?.cancel();
if (!completer.isCompleted) {
completer.complete(true);
}
}
});
// 设置超时
timeoutTimer = Timer(timeout, () {
progressTimer?.cancel();
if (!completer.isCompleted) {
completer.completeError(TimeoutException('文件上传超时', timeout));
}
});
return completer.future;
}
}
总结
Dart Timer是一个强大而灵活的异步编程工具,掌握其正确使用方法对于构建高性能的Dart应用程序至关重要。
关键要点:
- 合理选择Timer类型:一次性、周期性、立即执行
- 注意资源管理:及时取消不需要的Timer
- 错误处理:在Timer回调中进行适当的异常处理
- 性能优化:避免创建过多Timer,合理复用
- 内存泄漏预防:在组件销毁时清理Timer
实践建议:
- 在生产环境中使用Timer池管理大量定时任务
- 结合Future和Stream使用Timer构建复杂的异步流程
- 使用防抖和节流技术优化用户交互体验
- 实现重试机制提高应用程序的健壮性
通过掌握这些概念和技巧,您可以更好地利用Dart Timer构建高效、稳定的应用程序。