percent之Timer

因爲剛把集合中的list實現,而後Timer中又用到了列表,因此,這模塊將會有重構.
函數

重構好了,明天再將timer如何實現來簡單介紹一下.this

--------------------------------------------code

終於有時間將百分之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對象,這是如何實現的呢?不用着急,好菜立刻就要上了.rem

咱們先看一下TimerManager的createTimer方法須要傳入的參數,其參數定義以下:get

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的介紹到此結束.期待你們的評論與留言.

相關文章
相關標籤/搜索