percent之Timer

由于刚把集合中的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的介绍到此结束.期待大家的评论与留言.

你可能感兴趣的:(timer,as3.0)