当前位置:   article > 正文

[Flutter]倒计时和计时器

[Flutter]倒计时和计时器

1.延迟执行

Future.delayed

使用Future.delayed可以在延迟一定时间后执行代码。这是实现延迟执行最简单的方式之一。

  1. Future.delayed(Duration(seconds: 1), () {
  2. // 这里的代码会在1秒后执行
  3. print('This message is displayed after 1 second.');
  4. });

Timer

Timer类提供了更灵活的方式来实现单次或重复的延迟执行。

  1. // 单次延迟
  2. Timer(Duration(seconds: 1), () {
  3. // 这里的代码会在1秒后执行
  4. print('This message is displayed after 1 second.');
  5. });
  6. // 重复执行
  7. Timer.periodic(Duration(seconds: 1), (Timer t) {
  8. // 这里的代码会每1秒执行一次
  9. print('This message is displayed every 1 second.');
  10. });

AnimationController

在动画中,使用AnimationController可以在动画帧更新时执行代码,这可以用来实现延迟。

  1. AnimationController controller = AnimationController(
  2. duration: Duration(seconds: 1),
  3. vsync: this, // 需要一个TickerProvider类型的vsync参数
  4. );
  5. controller.forward().then((_) {
  6. // 这里的代码会在动画结束后执行
  7. print('This message is displayed after the animation ends.');
  8. });

Future

如果你已经在处理Future,也可以通过.then()链式调用在Future完成后延迟执行代码。

  1. someFuture().then((value) {
  2. // 做一些处理...
  3. }).then((_) {
  4. // 这里的代码会紧接着前一个then执行后执行
  5. print('This message is displayed after the future completes.');
  6. });

使用async和await

结合使用asyncawait关键字,可以让你在异步函数中顺序执行代码块,看起来像是同步代码。

  1. Future<void> delayedPrint() async {
  2. await Future.delayed(Duration(seconds: 1));
  3. print('This message is displayed after 1 second.');
  4. }
  5. delayedPrint();

进一步封装一下

  1. class Tools {
  2. // 延迟执行
  3. static void delayExecution(int second, void Function() callback) async {
  4. await Future.delayed(Duration(seconds: second));
  5. callback();
  6. }
  7. }
  8. Tools.delayExecution(3, () {
  9. print("execute");
  10. });

Isolates

当需要执行长时间运行的计算任务时,可以使用Isolates来实现不阻塞主线程的延迟执行。这在Flutter中用于并行计算或执行耗时任务。

  1. import 'dart:isolate';
  2. void longRunningTask(SendPort sendPort) {
  3. // 执行耗时任务
  4. sendPort.send(result);
  5. }
  6. void startIsolate() async {
  7. ReceivePort receivePort = ReceivePort();
  8. Isolate.spawn(longRunningTask, receivePort.sendPort);
  9. receivePort.listen((data) {
  10. // 获取到结果后执行的操作
  11. });
  12. }

在实际应用中,选择哪种方式取决于你的具体需求。对于简单的延迟执行,通常Future.delayedTimer就足够使用。而对于涉及动画或者复杂异步流程的情况,则可能需要使用AnimationController或者结合asyncawait的方式。对于需要后台执行的长时间运行任务,则可能需要使用Isolate

 

2.全局控制的倒计时

要创建一个全局定时器,可以通过单例模式封装一个定时器管理类。这个类可以提供启动、暂停、重启和关闭定时器的方法,并且确保定时完成后自动释放定时器资源。

以下是一个简单的全局定时器管理类示例:

  1. import 'dart:async';
  2. class GlobalTimer {
  3. static final GlobalTimer _instance = GlobalTimer._internal();
  4. Timer? _timer;
  5. factory GlobalTimer() {
  6. return _instance;
  7. }
  8. GlobalTimer._internal();
  9. void startTimer({
  10. required Duration delay,
  11. required VoidCallback action,
  12. }) {
  13. _timer?.cancel(); // 取消之前的计时器(如果存在)
  14. _timer = Timer(delay, () {
  15. action();
  16. // 计时器执行完成后释放资源
  17. _timer?.cancel();
  18. _timer = null;
  19. });
  20. }
  21. void pauseTimer() {
  22. if (_timer?.isActive ?? false) {
  23. _timer?.cancel();
  24. }
  25. }
  26. void resumeTimer({
  27. required Duration delay,
  28. required VoidCallback action,
  29. }) {
  30. pauseTimer(); // 先暂停计时器
  31. startTimer(delay: delay, action: action); // 重新开始计时器
  32. }
  33. void stopTimer() {
  34. _timer?.cancel();
  35. _timer = null;
  36. }
  37. bool isTimerActive() {
  38. return _timer?.isActive ?? false;
  39. }
  40. }

使用:

  1. // 启动定时器
  2. GlobalTimer().startTimer(
  3. delay: Duration(seconds: 5),
  4. action: () {
  5. print('Timer action executed after 5 seconds');
  6. },
  7. );
  8. // 暂停定时器
  9. GlobalTimer().pauseTimer();
  10. // 重启定时器
  11. GlobalTimer().resumeTimer(
  12. delay: Duration(seconds: 5),
  13. action: () {
  14. print('Timer action executed after another 5 seconds');
  15. },
  16. );
  17. // 停止定时器
  18. GlobalTimer().stopTimer();
  19. // 检查定时器是否活跃
  20. bool isActive = GlobalTimer().isTimerActive();

这个类使用了单例模式,确保全局只有一个GlobalTimer实例。startTimer方法用于设置定时器,接收延迟时间和要执行的动作。pauseTimer会暂停定时器,resumeTimer可以重启定时器,而stopTimer会停止定时器并释放资源。isTimerActive方法用于检查定时器是否在运行中。

这个类不是线程安全的,因为Dart本身是单线程的,但是如果你使用它在Flutter的Isolates(类似于线程)中,请确保你正确地管理状态。此外,如果你的应用需要更复杂的定时器调度,你可能需要考虑其他的包或者解决方案。

 

3.全局控制的计时器

要创建一个全局可控的计时器,你可以使用单例模式并结合StreamStreamController来实现计时器状态的全局订阅。这样,你可以在任何地方订阅计时器的变化,并实现回调更新。

以下是一个实现全局计时器的示例:

  1. import 'dart:async';
  2. class GlobalTimer {
  3. static final GlobalTimer _instance = GlobalTimer._internal();
  4. Timer? _timer;
  5. int _elapsedSeconds = 0;
  6. final StreamController<int> _streamController = StreamController<int>.broadcast();
  7. DateTime? _startTime;
  8. factory GlobalTimer() {
  9. return _instance;
  10. }
  11. GlobalTimer._internal();
  12. void startTimer() {
  13. if (_timer != null && _timer!.isActive) {
  14. // 如果计时器已经启动,则不做任何操作
  15. return;
  16. }
  17. _startTime = DateTime.now(); // 记录开始计时的时间戳
  18. _timer = Timer.periodic(Duration(seconds: 1), (Timer timer) {
  19. _elapsedSeconds++;
  20. _streamController.add(_elapsedSeconds); // 通过Stream通知订阅者
  21. });
  22. }
  23. void stopTimer() {
  24. _timer?.cancel();
  25. _timer = null;
  26. _elapsedSeconds = 0; // 重置累计时间
  27. _startTime = null;
  28. }
  29. int get elapsedSeconds => _elapsedSeconds;
  30. Stream<int> get timerStream => _streamController.stream;
  31. static String formatDuration(int totalSeconds) {
  32. int hours = totalSeconds ~/ 3600;
  33. int minutes = (totalSeconds % 3600) ~/ 60;
  34. int seconds = totalSeconds % 60;
  35. String hoursStr = (hours).toString().padLeft(2, '0');
  36. String minutesStr = (minutes).toString().padLeft(2, '0');
  37. String secondsStr = (seconds).toString().padLeft(2, '0');
  38. return "$hoursStr:$minutesStr:$secondsStr";
  39. }
  40. void dispose() {
  41. _streamController.close();
  42. }
  43. }

使用:

  1. // 启动计时器
  2. GlobalTimer().startTimer();
  3. // 停止计时器
  4. GlobalTimer().stopTimer();
  5. // 获取当前累计计时时长
  6. int seconds = GlobalTimer().elapsedSeconds;
  7. // 格式化计时显示
  8. String formattedTime = GlobalTimer.formatDuration(seconds);
  9. // 订阅计时变化
  10. GlobalTimer().timerStream.listen((int elapsedSeconds) {
  11. print('Timer updated: $elapsedSeconds seconds');
  12. // 更新页面等...
  13. });
  14. // 释放资源
  15. GlobalTimer().dispose();

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/170405
推荐阅读
相关标签
  

闽ICP备14008679号