Timer是时钟管理类,在Laya初始化的时候会创建一个实例,通过Laya.timer访问。

TimerHandler
  • TimerHandler是对每一个定时任务的封装,每次调用frameOnce、frameLoop、once、loop或者callLayer都会产生一个TimerHandler实例。
  • TimerHandler会缓存传入的参数(args),当定时器触发时,会将对应的args传递给对应回调。
public var key:int;             //唯一key,用于快速找到对应handler
public var repeat:Boolean;      //是否是重复调用   分别对应 once/loop
public var delay:int;           //延时
public var userFrame:Boolean;   // true表示使用帧计时  false表示使用时间计时
public var exeTime:int;         //下次执行的时间
public var caller:*             //调用者
public var method:Function;     //调用方法
public var args:Array;          //触发时的参数
public var jumpFrame:Boolean;   //时钟是否跳帧。基于时间的循环回调,单位时间间隔内,如能执行多次回调,出于性能考虑,引擎默认只执行一次,设置jumpFrame=true后,则回调会连续执行多次public function clear():void {caller = null;method = null;args = null;
}public function run(withClear:Boolean):void {var caller:* = this.caller;/*[IF-FLASH]*/if ((caller is Node) && caller.destroyed)/*[IF-FLASH]*/return clear();//[IF-SCRIPT] if (caller && caller.destroyed) return clear();var method:Function = this.method;var args:Array = this.args;withClear && clear();if (method == null) return;args ? method.apply(caller, args) : method.call(caller);
}
Timer数据类型定义
/**@private */
private static var _pool:Array = [];   //TimerHandler池/*[DISABLE-ADD-VARIABLE-DEFAULT-VALUE]*/
/** 两帧之间的时间间隔,单位毫秒。*/
private var _delta:int = 0;
/** 时针缩放。*/
public var scale:Number = 1;
/** 当前帧开始的时间。*/
public var currTimer:Number = _now();
/** 当前的帧数。*/
public var currFrame:int = 0;
/**@private */
private var _lastTimer:Number = _now(); //上一帧的时间
/**@private */
private var _mid:int = 1;               //用于生成唯一key
/**@private */
/*[IF-FLASH]*/                          //TimerHandler的map  用于查找Handler(包括Later的handler)
private var _map:flash.utils.Dictionary = new flash.utils.Dictionary(true);
//[IF-JS] private var _map:Array = [];
/**@private */
private var _laters:Array = [];         //存放callLater创建的handler
/**@private */
private var _handlers:Array = [];       //存放非callLater创建的handler,包括frameOnce、frameLoop、once、loop
/**@private */
private var _temp:Array = [];           //临时数组,用于清理
/**@private */
private var _count:int = 0;             //记录handler.method为空的数量,检测是否清理
初始化
/**@private */
protected function _init():void {Laya.timer && Laya.timer.frameLoop(1, this, _update);
}

除了Laya.timer之外,其他的timer的实例都是注册到Laya.timer的frameLoop中。

_create方法
  • 创建对应的TimerHandler。
  • 如果coverBefore并且已经注册过相同Handler,则覆盖之前的handler
  • 设置对应参数,并计算下一次执行的时间。
  • 为Handler创建唯一key,添加到_map中,用于快速查找。
  • 将handler放到_handler数组中,用于_update时遍历。

frameOnce、frameLoop、once、loop实现上都是调用_create方法,传入对应的参数,将handler注册到timer中,等待_update执行相关计算。

/** @private */
public function _create(useFrame:Boolean, repeat:Boolean, delay:int, caller:*, method:Function, args:Array, coverBefore:Boolean):TimerHandler {//如果延迟为0,则立即执行if (!delay) {method.apply(caller, args);return null;}//先覆盖相同函数的计时if (coverBefore) {var handler:TimerHandler = _getHandler(caller, method);if (handler) {handler.repeat = repeat;handler.userFrame = useFrame;handler.delay = delay;handler.caller = caller;handler.method = method;handler.args = args;handler.exeTime = delay + (useFrame ? this.currFrame : this.currTimer + _now() - _lastTimer);return handler;}}//找到一个空闲的timerHandlerhandler = _pool.length > 0 ? _pool.pop() : new TimerHandler();handler.repeat = repeat;handler.userFrame = useFrame;handler.delay = delay;handler.caller = caller;handler.method = method;handler.args = args;handler.exeTime = delay + (useFrame ? this.currFrame : this.currTimer + _now() - _lastTimer) + 1;//索引handler_indexHandler(handler);//插入数组_handlers.push(handler);return handler;
}
callLater
  • callLater使用延时执行,再Timer.update执行末尾调用。
  • 如果对应的caller和method已经注册过,则不会重复注册。
  • 创建的TimerHandler会放到_laters数组中。
_update
  • 计算当前帧和当前时间。
  • 计算delta。
  • 遍历handler数组,检查时间/帧是否超过了handler的exeTime。
  • 超过时间handler执行回调,如果是once则将handler的caller和method设置为空;如果是loop则执行回调,并计算下次执行的时间。如果下次调用的时间间隔内,可以触发多次回调,默认情况下执行执行一次回调。如果设置为jumpFrame则会调用多次回调(如delay为1毫秒,delta为30毫秒,则下个update时,会调用30次回调)。
  • 遍历数组时,会记录method为空的handler的数量,当数量为30或者200帧时,会清理一次没用的handler,将没用的handler回收到池中。
  • 执行完所有handler之后,遍历所有laters数组,执行callLater所注册的回调。执行完成后,清理所有laters数组。
/*** @private* 帧循环处理函数。*/
public function _update():void {if (scale <= 0) {_lastTimer =_now();return;}var frame:int = this.currFrame = this.currFrame + scale;var now:Number = _now();_delta = (now - _lastTimer) * scale;var timer:Number = this.currTimer = this.currTimer + _delta;_lastTimer = now;//处理handlervar handlers:Array = this._handlers;_count = 0;for (i = 0, n = handlers.length; i < n; i++) {handler = handlers[i];if (handler.method !== null) {var t:int = handler.userFrame ? frame : timer;if (t >= handler.exeTime) {if (handler.repeat) {if (!handler.jumpFrame) {handler.exeTime += handler.delay;handler.run(false);if (t > handler.exeTime) {//如果执行一次后还能再执行,做跳出处理,如果想用多次执行,需要设置jumpFrame=truehandler.exeTime += Math.ceil((t - handler.exeTime) / handler.delay) * handler.delay;}} else {while (t >= handler.exeTime) {handler.exeTime += handler.delay;handler.run(false);}}} else {handler.run(true);}}} else {_count++;}}if (_count > 30 || frame % 200 === 0) _clearHandlers();//处理callLatervar laters:Array = this._laters;for (var i:int = 0, n:int = laters.length - 1; i <= n; i++) {var handler:TimerHandler = laters[i];if (handler.method !== null) {/*[IF-FLASH]*/_map[handler.method] = null;//[IF-SCRIPT]_map[handler.key] = null;handler.run(false);}_recoverHandler(handler);i === n && (n = laters.length - 1);}laters.length = 0;
}
其他
  • Laya.timer._update是在Laya.stage.loop中调用,Laya.stage.loop是在Render中调用。

  • 在Frash中,监听enterFrame事件。

  • 在js中则是注册requestAnimationFrame,来进入渲染帧。

  • 当stage不可见时(如切到后台),则timer._update每一秒触发一次。一秒钟一帧,当切回前台后,帧率恢复正常。

  • update是在渲染之前执行。
  • Laya.stage控制实际帧率,根据Laya.stage.frameRate。

转载于:https://www.cnblogs.com/chiguozi/p/9755808.html

Laya1.x Timer小记相关推荐

  1. JavaScript小记(持续更新)

    注意:(2020.01.14) 后续将都在我的学习笔记文档 - JavaScript小记中进行更新,该文章不再更新,请持续关注上述网页 学习js遇到的疑问和js基础都记录在这里,持续更新中. 2019 ...

  2. Xv6学习小记(二)——多核启动

    本文首发于我的个人博客QIMING.INFO,转载请带上链接及署名.(注:本文代码中的注释很重要,如看不清,可移步我的个人博客中查看) 在上文(Xv6学习小记(一)--编译与运行)中,我们介绍了Lin ...

  3. Timer定时器开发

    Timer定时器开发 定时器的作用是不占线程的等待一个确定时间,同样通过callback来通知定时器到期. 参考:https://github.com/sogou/workflow 定时器的创建 同样 ...

  4. Timer 的简单介绍

    1 Timer timer=new Timer(); (个人建议使用的时候不要直接就new一个,原因是,还没使用呢就先分配一个空间, 我们使用private Timer timer: 然后在使用前  ...

  5. nordic 51822 sdk. timer 的使用

    它的源代码和头文件分别为app_timer.c/app_timer.h.这是Nordic为我们提供的虚拟定时器,这个定时器不同于硬件上的TIMER,而是基于RTC1实现的一种虚拟定时器,其将定时功能作 ...

  6. Standup Timer的MVC模式及项目结构分析

    前言 学习android一段时间了,为了进一步了解android的应用是如何设计开发的,决定详细研究几个开源的android应用.从一些开源应用中吸收点东西,一边进行量的积累,一边探索android的 ...

  7. C# Timer使用方法示例

    实例化一个timer: // 每5分钟执行一次,每次执行的间隔毫秒时长 System.Timers.Timer timer = new System.Timers.Timer(5*60*1000); ...

  8. C#中Timer组件用法

    Timer组件是也是一个WinForm组件了,和其他的WinForm组件的最大区别是:Timer组件是不可见的,而其他大部分的组件都是都是可见的,可以设计的.Timer组件也被封装在名称空间Syste ...

  9. Android Timer的使用

    1:服务端使用PHP <?phpecho date('Y-m-d H:i:s'); ?> 2:activity_main.xml <RelativeLayout xmlns:andr ...

最新文章

  1. mysql拼接两个字段_重拾MySQL之创建计算字段和函数
  2. 日常生活小技巧 -- vmware workstation 无法连接到虚拟机
  3. 话里话外:ERP与PDM、MES的关系区别是什么
  4. 空间统计分析_【空间分析】地理探测器原理
  5. LintCode 4.丑数
  6. YOLOv5:道路损伤检测
  7. DEVC++下载与环境配置,手把手教程
  8. java 发卡平台支付_基于jsp的自动发卡平台-JavaEE实现自动发卡平台 - java项目源码...
  9. 铅酸电池充电C语言程序,铅酸电池如何充电_铅酸电池充电原理 - 全文
  10. 易佰USB转串口驱动
  11. 数商云:传统建筑行业产业转型,轻松实现建筑材料信息系统撮合交易智能化、数字化管理
  12. 计算机死机代码怎么写,如何用代码让电脑死机
  13. 南邮CTF逆向题第三道Py交易解题思路
  14. item2vec--word2vec在推荐领域的使用
  15. IVCam:电脑调用你的手机摄像头
  16. idea 修改远程 git仓库地址到阿里云code 推送
  17. 开发者证书、授权文件的管理
  18. 软件测试专业院校研究生,北化信息科学与技术学院导师赵瑞莲【计算机考研软件测试与软件可靠性方向】...
  19. 路由器免刷固件连接校园网(蝴蝶客户端)
  20. Docker Desktop is stopped on macOS Ventura: Unable to calculate image disk size

热门文章

  1. Akka默认20s超时修改配置
  2. Windows Terminal + WSL2 + CENTOS 配置Windows命令终端
  3. Wannafly挑战赛29-御坂美琴(递归模拟)
  4. 所谓键位冲突和无冲突的各种原理
  5. (转载)0x0F1AFD76 (libcocos2d.dll) (Plane.exe 中)处有未经处理的异常: 0xC0000005: 读取位置 0x00000018 时发生访问冲突。
  6. java 隐藏父类方法,java 子类继承父类成员变量的隐藏、实现方法的重写
  7. 【懒懒的Python学习笔记七】
  8. 联想集团:2021/22财年第一季度业绩
  9. 华为使用计算机投屏要打开什么,华为Mate20手机怎么投屏到电脑上呢
  10. 【实战】(字节跳动、日本东京大学)学习使用白盒表示+GAN来创作卡通图片:Learning to Cartoonize Using White-Box Cartoon Representations