[Flutter]倒计时和计时器

1.延迟执行

Future.delayed

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

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

Timer

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

// 单次延迟
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可以在动画帧更新时执行代码,这可以用来实现延迟。

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完成后延迟执行代码。

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

使用async和await

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

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

delayedPrint();

进一步封装一下

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中用于并行计算或执行耗时任务。

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.全局控制的倒计时

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

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

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;
  }
}

使用:

// 启动定时器
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来实现计时器状态的全局订阅。这样,你可以在任何地方订阅计时器的变化,并实现回调更新。

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

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();
  }
}

使用:

// 启动计时器
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();

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/418070.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

kswapd0挖矿病毒攻击记录

文章目录 一、起因与病毒分析1、起因2、阿里云告警2.1 恶意脚本代码执行12.2 恶意脚本代码执行22.3恶意脚本代码执行32.4 恶意脚本代码执行4 3、病毒简单分析3.1 病毒的初始化3.2 病毒本体执行 4、总结 二、ubuntu自救指南1、病毒清理2、如何防御 一、起因与病毒分析 1、起因 …

蓝桥杯 信号覆盖

遍历每一个坐标轴上的点&#xff0c;带入圆的方程&#xff0c;看是否在圆内或圆上 #include<bits/stdc.h> using namespace std; int main() {int w,h,n,r,i,j,k,s,ans0;cin>>w>>h>>n>>r;int x[n1],y[n1];for(i0;i<n;i){cin>>x[i]>&…

什么是前端框架中的数据绑定(data binding)?有哪些类型的数据绑定?

聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 欢迎来到前端入门之旅&#xff01;感兴趣的可以订阅本专栏哦&#xff01;这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…

Linux读写锁相关函数及操作

读写锁&#xff1a; 概念&#xff1a;读写锁也叫共享-独占锁。当读写锁以读模式锁住时&#xff0c;它是以共享模式锁住的&#xff1b;当它以写模式锁住时&#xff0c;它是以独占模式锁住的。&#xff08;写独占&#xff0c;读共享&#xff09;。 读写锁使用场所&#xff1a; …

基于PHP的在线英语学习平台

有需要请加文章底部Q哦 可远程调试 基于PHP的在线英语学习平台 一 介绍 此在线英语学习平台基于原生PHP开发&#xff0c;数据库mysql。系统角色分为学生&#xff0c;教师和管理员。(附带参考设计文档) 技术栈&#xff1a;phpmysqlphpstudyvscode 二 功能 学生 1 注册/登录/…

编译 qsqlmysql.dll QMYSQL driver not loaded

Qt 连接MySQL数据库&#xff0c;没有匹配的qsqlmysql.dll, 需要我们跟进自己Mysql 以及QT版本自行编译的。异常如下图&#xff1a; 安装环境为 VS2019 Qt5.12.12&#xff08;msvc2017_64、以及源码&#xff09; 我的安装地址&#xff1a;D:\Qt\Qt5.12.12 Mysql 8.1.0 默认安…

【Kotlin】函数

1 常规函数 1.1 无参函数 fun main() {myFun() }fun myFun() {println("myFun") // 打印: myFun } 1.2 有参函数 1&#xff09;常规调用 fun main() {myFun("myFun") // 打印: myFun }fun myFun(str: String) {println(str) } 2&#xff09;形参指定默…

Redis高级应用——海量数据高并发下Reids的分片集群,原理和应用,集群伸缩以及项目配置

目录 引出Reids海量数据&#xff0c;高并发问题认识Redis集群算法搭建Redis分片集群准备实例安装redis启动 创建集群测试 分片集群原理搭建分片集群散列插槽插槽原理小结 认识集群伸缩需求分析创建新的redis实例添加新节点到redis集群转移插槽自动故障转移 SpringBoot配置Redis…

基于YOLOv8深度学习的复杂场景下船舶目标检测系统【python源码+Pyqt5界面+数据集+训练代码】深度学习实战、目标检测

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌更多学习资源&#xff0c;可关注公-仲-hao:【阿旭算法与机器学习】&#xff0c;共同学习交流~ &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推…

Bash命令启动、关闭、重启Jar包

1、创建文件夹&#xff0c;将项目jar文件丢入服务器中 mkdir -m 755 test -m&#xff1a;类似chmod 给文件夹权限 2、一般开发环境和部署环境配置不一致&#xff0c;在有外置配置及内置配置时&#xff0c;JAR优先使用外置配置文件&#xff0c;即将外置配置文件修改好之后&am…

利用python爬取本站的所有博客链接

目录 前因 首先的尝试 解决办法 导入包 定义一个json配置文件 打开浏览器执行操作 注意 提取源代码并且进行筛选链接 执行结果 前因 由于自己要把csdn的博客同步到hugo中&#xff0c;把博客转为md格式已经搞好了&#xff0c;但是由于csdn的图片具有防盗链&#xff0c;…

Nginx多次代理后获取真实的用户IP访问地址

需求&#xff1a;记录用户操作记录&#xff0c;类似如下表格的这样 PS: 注意无论你的服务是Http访问还是Https 访问的都是可以的&#xff0c;我们服务之前是客户只给开放了一个端口&#xff0c;但是既要支持https又要支持http协议&#xff0c;nginx 是可以通过stream 模块配置双…

Prometheus-监控远程linux的主机

一、本地访问 1、访问 http://8.137.122.212:9090/2、查看监控的主机 默认只监控了本机一台主机 这里的IP地址原本是‘localhost’&#xff0c;为了方便我将‘localhost’换成了主机的IP地址 现在看只监控了本机一台主机 3、查看监控数据 通过http://8.137.122.212:9090/m…

十五、集合进阶——不可变集合 、Stream流 和 方法引用

不可变集合 和 Stream流 一、创建不可变集合二、Stream流2.1 初识Stream流2.2Stream流的中间方法2.3Stream流的终结方法 三、练习练习1&#xff1a;数据过滤练习2&#xff1a;数据操作练习3&#xff1a;数据操作 四、方法引用4.1 初识 方法引用4.2 引用 静态方法4.3 引用 成员方…

七通道NPN 达林顿管GC2003,专为符合标准 TTL 而制造,最高工作电压 50V,耐压 80V

GC2003 内部集成了 7 个 NPN 达林顿晶体管&#xff0c;连接的阵列&#xff0c;非常适合逻辑接口电平数字电路&#xff08;例 如 TTL&#xff0c;CMOS 或PMOS 上/NMOS&#xff09;和较高的电流/电压&#xff0c;如电灯电磁阀&#xff0c;继电器&#xff0c;打印机或其他类似的负…

形态学笔记:侵蚀+膨胀+开运算+闭运算+形态学梯度+顶帽运算+黑帽运算

形态学 一般在二值图上操作 输入&#xff1a;原图、操作结构内核 简单阈值 对于每个像素&#xff0c;应用相同的阈值。如果像素值小于阈值&#xff0c;则将其设置为0&#xff0c;否则将其设置为最大值 原图–>灰度图–>二值图 logo cv2.imread(./fans.jpg) # 参数1 …

初学HTMLCSS——盒子模型

盒子模型 盒子&#xff1a;页面中所有的元素&#xff08;标签&#xff09;&#xff0c;都可以看做是一个 盒子&#xff0c;由盒子将页面中的元素包含在一个矩形区域内&#xff0c;通过盒子的视角更方便的进行页面布局盒子模型组成&#xff1a;内容区域&#xff08;content&…

双指针问题(Java编写)

日升时奋斗&#xff0c;日落时自省 目录 一、移动零 二、盛水最多的容器 三、快乐数 四、复写零 五、三数之和 六、有效三角形的个数 七、四数之和 一、移动零 题目来源&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 题目主要内容就是将数组中所有的零移动到…

FPGA高端项目:FPGA基于GS2971的SDI视频接收+图像缩放,提供3套工程源码和技术支持

目录 1、前言免责声明 2、相关方案推荐本博已有的 SDI 编解码方案本方案的SDI接收转HDMI输出应用本方案的SDI纯verilog图像缩放视频拼接应用本方案的SDI HLS图像缩放视频拼接应用本方案的SDI视频编码动态字符叠加输出应用本方案的SDI视频编码多路视频融合视频叠加应用FPGA的SDI…

Redis 群集部署

部署配置实验 实验环境 虚拟机 6台 centos7.9 网卡NAT模式 数量 1 组件包Redis安装包 设备 IP 备注 Centos01 192.168.9.31 Node1 Centos02 192.168.9.32 Node2 Centos03 192.168.9.33 Node3 Centos04 192.168.9.34 Node4 Centos05 192.168.9.35 Node5 C…
最新文章