[Flutter]倒计时和计时器

1.延迟执行

Future.delayed

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

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

Timer

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

Dart 复制代码
// 单次延迟
Timer(Duration(seconds: 1), () {
  // 这里的代码会在1秒后执行
  print('This message is displayed after 1 second.');
});

// 重复执行
Timer.periodic(Duration(seconds: 1), (Timer t) {
  // 这里的代码会每1秒执行一次
  print('This message is displayed every 1 second.');
});

AnimationController

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

Dart 复制代码
AnimationController controller = AnimationController(
  duration: Duration(seconds: 1),
  vsync: this, // 需要一个TickerProvider类型的vsync参数
);

controller.forward().then((_) {
  // 这里的代码会在动画结束后执行
  print('This message is displayed after the animation ends.');
});

Future

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

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

使用async和await

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

Dart 复制代码
Future<void> delayedPrint() async {
  await Future.delayed(Duration(seconds: 1));
  print('This message is displayed after 1 second.');
}

delayedPrint();

进一步封装一下

Dart 复制代码
class Tools {
  // 延迟执行
  static void delayExecution(int second, void Function() callback) async {
    await Future.delayed(Duration(seconds: second));
    callback();
  }
}

Tools.delayExecution(3, () {
    print("execute");
});

Isolates

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

Dart 复制代码
import 'dart:isolate';

void longRunningTask(SendPort sendPort) {
  // 执行耗时任务
  sendPort.send(result);
}

void startIsolate() async {
  ReceivePort receivePort = ReceivePort();
  Isolate.spawn(longRunningTask, receivePort.sendPort);

  receivePort.listen((data) {
    // 获取到结果后执行的操作
  });
}

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

2.全局控制的倒计时

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

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

Dart 复制代码
import 'dart:async';

class GlobalTimer {
  static final GlobalTimer _instance = GlobalTimer._internal();
  Timer? _timer;

  factory GlobalTimer() {
    return _instance;
  }

  GlobalTimer._internal();

  void startTimer({
    required Duration delay,
    required VoidCallback action,
  }) {
    _timer?.cancel(); // 取消之前的计时器(如果存在)
    _timer = Timer(delay, () {
      action();
      // 计时器执行完成后释放资源
      _timer?.cancel();
      _timer = null;
    });
  }

  void pauseTimer() {
    if (_timer?.isActive ?? false) {
      _timer?.cancel();
    }
  }

  void resumeTimer({
    required Duration delay,
    required VoidCallback action,
  }) {
    pauseTimer(); // 先暂停计时器
    startTimer(delay: delay, action: action); // 重新开始计时器
  }

  void stopTimer() {
    _timer?.cancel();
    _timer = null;
  }

  bool isTimerActive() {
    return _timer?.isActive ?? false;
  }
}

使用:

Dart 复制代码
// 启动定时器
GlobalTimer().startTimer(
  delay: Duration(seconds: 5),
  action: () {
    print('Timer action executed after 5 seconds');
  },
);

// 暂停定时器
GlobalTimer().pauseTimer();

// 重启定时器
GlobalTimer().resumeTimer(
  delay: Duration(seconds: 5),
  action: () {
    print('Timer action executed after another 5 seconds');
  },
);

// 停止定时器
GlobalTimer().stopTimer();

// 检查定时器是否活跃
bool isActive = GlobalTimer().isTimerActive();

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

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

3.全局控制的计时器

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

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

Dart 复制代码
import 'dart:async';

class GlobalTimer {
  static final GlobalTimer _instance = GlobalTimer._internal();
  Timer? _timer;
  int _elapsedSeconds = 0;
  final StreamController<int> _streamController = StreamController<int>.broadcast();

  DateTime? _startTime;

  factory GlobalTimer() {
    return _instance;
  }

  GlobalTimer._internal();

  void startTimer() {
    if (_timer != null && _timer!.isActive) {
      // 如果计时器已经启动,则不做任何操作
      return;
    }
    _startTime = DateTime.now(); // 记录开始计时的时间戳
    _timer = Timer.periodic(Duration(seconds: 1), (Timer timer) {
      _elapsedSeconds++;
      _streamController.add(_elapsedSeconds); // 通过Stream通知订阅者
    });
  }

  void stopTimer() {
    _timer?.cancel();
    _timer = null;
    _elapsedSeconds = 0; // 重置累计时间
    _startTime = null;
  }

  int get elapsedSeconds => _elapsedSeconds;

  Stream<int> get timerStream => _streamController.stream;

  static String formatDuration(int totalSeconds) {
    int hours = totalSeconds ~/ 3600;
    int minutes = (totalSeconds % 3600) ~/ 60;
    int seconds = totalSeconds % 60;

    String hoursStr = (hours).toString().padLeft(2, '0');
    String minutesStr = (minutes).toString().padLeft(2, '0');
    String secondsStr = (seconds).toString().padLeft(2, '0');

    return "$hoursStr:$minutesStr:$secondsStr";
  }

  void dispose() {
    _streamController.close();
  }
}

使用:

Dart 复制代码
// 启动计时器
GlobalTimer().startTimer();

// 停止计时器
GlobalTimer().stopTimer();

// 获取当前累计计时时长
int seconds = GlobalTimer().elapsedSeconds;

// 格式化计时显示
String formattedTime = GlobalTimer.formatDuration(seconds);

// 订阅计时变化
GlobalTimer().timerStream.listen((int elapsedSeconds) {
  print('Timer updated: $elapsedSeconds seconds');
  // 更新页面等...
});

// 释放资源
GlobalTimer().dispose();
相关推荐
程序员老刘2 小时前
一杯奶茶钱,PicGo + 阿里云 OSS 搭建永久稳定的个人图床
flutter·markdown
奋斗的小青年!!5 小时前
OpenHarmony Flutter 拖拽排序组件性能优化与跨平台适配指南
flutter·harmonyos·鸿蒙
小雨下雨的雨6 小时前
Flutter 框架跨平台鸿蒙开发 —— Stack 控件之三维层叠艺术
flutter·华为·harmonyos
行者967 小时前
OpenHarmony平台Flutter手风琴菜单组件的跨平台适配实践
flutter·harmonyos·鸿蒙
小雨下雨的雨9 小时前
Flutter 框架跨平台鸿蒙开发 —— Flex 控件之响应式弹性布局
flutter·ui·华为·harmonyos·鸿蒙系统
cn_mengbei9 小时前
Flutter for OpenHarmony 实战:CheckboxListTile 复选框列表项详解
flutter
cn_mengbei9 小时前
Flutter for OpenHarmony 实战:Switch 开关按钮详解
flutter
奋斗的小青年!!9 小时前
OpenHarmony Flutter实战:打造高性能订单确认流程步骤条
flutter·harmonyos·鸿蒙
Coder_Boy_9 小时前
Flutter基础介绍-跨平台移动应用开发框架
spring boot·flutter
cn_mengbei9 小时前
Flutter for OpenHarmony 实战:Slider 滑块控件详解
flutter