由于刚把集合中的list实现,然后Timer中又用到了列表,所以,这模块将会有重构.
重构好了,明天再将timer如何实现来简单介绍一下.
--------------------------------------------
终于有时间将百分之Timer系统的说一下了.
首先,百分之Timer提供了一个TimerManager单例对象,用来提供生成Timer的工厂,使用起来很简单,代码如下所示(局部代码):
var timer1:ITimer = TimerManager.instance.createTimer(1000 , onTimer1 , ["on timer 1"]); var timer2:ITimer = TimerManager.instance.createTimer(1000 , onTimer1 , ["on timer 2"]); var timer3:ITimer = TimerManager.instance.createTimer(2000 , onTimer1 , ["on timer 3"]); timer1.start(); timer2.start(); timer3.start()
private function onTimer1(message:String):void { trace(message); }
通过TimerManager提供的creatTimer方法,可以很方便的生成一个ITimer对象,然后调用ITimer的start方法,onTimer1将会每隔一段时间,被执行一次.
关键处在于上面生成的三个ITimer对象,将会共享同一个Timer对象,这是如何实现的呢?不用着急,好菜马上就要上了.
我们先看一下TimerManager的createTimer方法需要传入的参数,其参数定义如下:
public function createTimer(delay:int , fn:Function , fnParams:Array = null):ITimer
delay(int) :延迟,以毫秒为单位,表示每次回调函数被执行的时间间隔,与系统自带的Timer的delay含义一致.
fn(Function):回调函数
fnParams(Array):回调函数的参数列表
相信不少同学在看到这里的时候,已经可以猜到百分之Timer的实现原理,在不继续看下去的情况下,也能自己实现了.不过,光看一个createTimer,显然不是大家想要看到的结果.createTimer的源码为:
public function createTimer(delay:int , fn:Function , fnParams:Array = null):ITimer { var callback:FN = new FN(fn , fnParams); var timer:ITimer = new MyTimer(delay , callback); add(timer); return timer; }
代码其实一目了然,重点在add方法,其源码为:
private function add(timer:ITimer):void { if(timer.delay < 0) return; //遍历列表,找出其中是否存在与timer的delay成正比的执行者 var sets:ISet = _executers.getKeys(); for(var i:int = 0 ;i < sets.size ; i++) { if(timer.delay % sets.getValue(i) == 0) { (_executers.getValue(sets.getValue(i)) as ITimerExecuter).add(timer); break; } } // if(!timer.hasExecuter) { var executer:ITimerExecuter = new TimerExecuter(timer.delay); _executers.put(timer.delay , executer); executer.add(timer); } }
代码也不复杂,只是稍微比createTimer多了几行,一行行看过去,会发现,其实很简单.
一开始我判断了一下timer的delay是否大于0,若小于0,直接返回,这个是属于容错处理.
然后,我取得_executers的所有键值,我们看下_executers是个什么东西.
private var _executers:IMap; //执行列表
非常有必要将IMap贴出来看下,
public interface IMap { /** 插入一条数据*/ function put(key:* , value:*):void ; /** 删除一条数据*/ function remove(key:*):void; /** 返回指定key是否存在*/ function hasKeys(key:*):Boolean; /** 返回指定value是否存在*/ function contains(value:*):Boolean; /** 根据指定的key取得数据*/ function getValue(key:*):*; /** 取得key的集*/ function getKeys():ISet; /** 取得数据列表*/ function getValues():IList; }
注释的很明了,就不多说了.详细有关IMap的介绍,可以查看百分之集合,这个还没有写出来,之后有时间会写一下的.
回到add方法,在取出了_executers的键值集后,我采取了遍历该无重复项的集合,让其值与timer的delay值进行一个求余的操作,若为0,也就是刚好整除的情况下,取得该ITimerExecuter,并将timer添加进该ITimerExecuter.若遍历了所有键值还不存在一个符合条件的ITimerExecuter的话,便实例化一个以timer的delay值为其delay值,并以delay为键值,存储在_executers中.add方法到此结束 .在这里,有必要说明一下ITimerExecuter这个接口及其实现.
ITimerExecuter接口定义如下:
public interface ITimerExecuter { function add(timer:ITimer):void; function remove(timer:ITimer):void; function get isEmpty():Boolean; }
这个接口没加注释,因为它很简单,光看名字就知道了.接下来,我们来看一下它的实现类TimerExecuter,部分源码如下:
成员变量:
private var _delay:int; private var _timers:IList; private var _timersCount:IList; private var _timer:Timer;
构造函数:
public function TimerExecuter(delay:int = 10) { _timers = new List(); _timersCount = new List(); _delay = delay; _timer = new Timer(delay); _timer.addEventListener(TimerEvent.TIMER , onTimer); _timer.start(); }
关于IList的说明,详见百分之集合.在构造函数中,实例化了一个Timer对象,并监听了TimerEvent.TIMER事件.其回调函数为onTimer,我们来看onTimer的实现:
protected function onTimer(event:TimerEvent):void { if(isEmpty) return; for(var i:int = 0 ;i < _timers.size ; i++) { var t:ITimer = _timers.getValue(i); if(t.isExecute) { if(_timersCount.getValue(i) <= 0) { t.callback.execute(); _timersCount.replace(i , getDelayCount(t)); } else { var count:int = _timersCount.getValue(i); count = count - 1; _timersCount.replace(i , count); } } } }
其实就是遍历_timer列表,判断每一个timer是否可执行,若可执行,则判断其timer对应的timerCount的值是否不大于0,若是,则执行timer的回调函数,并更新其对应的timerCount值.若不是,则将对应的timerCount减一.getDelayCount的实现如下:
private function getDelayCount(timer:ITimer):int { return timer.delay/delay - 1; }
so easy.不多说了.百分之Timer的核心实现已经介绍了一遍了.最基本重要的ITimer却还没有说明,来看下其接口定义吧:
public interface ITimer { /** 执行间隔 */ function get delay():int; /** 回调函数 */ function get callback():FN; /** 设置 执行者 */ function set executer(value:ITimerExecuter):void; /** 取得执行者是否存在 */ function get hasExecuter():Boolean; /** 取得是否处于执行状态中 */ function get isExecute():Boolean; /** 开始执行*/ function start():void; /** 停止执行 */ function stop():void; /** 回收 */ function recover():void; }
都有注释,不需要多说了吧.其实现类MyTimer也很简单.部分代码如下:
成员变量:
private var _delay:int; private var _callback:FN; private var _isExecute:Boolean; private var _executer:ITimerExecuter;
start方法为:
public function start():void { _isExecute = true; }
remove方法为:
public function recover():void { _executer.remove(this); }
其它的都很简单,一看start及remove方法就知道,其它的方法有多简单了.
百分之Timer的介绍到此结束.期待大家的评论与留言.