Last active
December 15, 2015 16:48
-
-
Save lynxerzhang/5291265 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package | |
{ | |
import flash.utils.Dictionary; | |
/** | |
* 1.robertPenner的Signal如果在遍历中直接修改存储signal的链表, 则不会反映到当前遍历中(会在下一次派发中体现) | |
* 2.PureMVC中存储Observer的数组, 最终进行播报Notification时, 也是如此(先复制一份当前结构的副本,以避免播报过程中数组索引被修改) | |
* 3.RichardLord的Ash框架中使用链表结构实现了自己的Signal, 可以实现在播报Signal监听方法时, 直接修改(删除,添加)链表结构 | |
* 4.jacksondunstan的turbosignals利用了内置的数组结构, 和robertPannner的Signal一样, 但是和PureMVC不同的是, | |
* jacksondunstan直接使用了数组的内置方法进行复制, 而不是通过循环。 | |
* | |
* 该类的dispatch方法参考Starling框架的Juggler动画管理类对存储在内部数组的对象的动态管理。 | |
* | |
* @example | |
* | |
* var s:Signals = new Signals; | |
* s.add(test1); | |
* s.add(test2); | |
* s.add(test3); | |
* ... ... | |
* function test2():void{ | |
* s.remove(test3); //直接在播报中删除test3, test3方法将不再被执行 | |
* s.add(test4); //该方法为新添加, 所以本轮的播报不会触发, 需要在下一次的 | |
* //dispatch中触发 | |
* } | |
* s.dispatch(); | |
*/ | |
public class Signals | |
{ | |
public function Signals() | |
{ | |
} | |
/** | |
* 记录是否只执行一次即删除 | |
*/ | |
private var onceCheck:Dictionary = new Dictionary(false); | |
/** | |
* 记录所有监听方法 | |
*/ | |
private var base:Vector.<Function> = new <Function>[]; | |
/** | |
* 记录监听方法数量 | |
*/ | |
private var count:int = 0; | |
/** | |
* 添加一个监听方法 | |
* @param fun | |
* @param executeOnce | |
*/ | |
public function add(fun:Function, executeOnce:Boolean = false):void{ | |
if(!contain(fun)){ | |
onceCheck[fun] = new Node(executeOnce, base.push(fun) - 1); | |
count++; | |
} | |
} | |
/** | |
* 移除一个方法 | |
*/ | |
public function remove(fun:Function):void{ | |
if(contain(fun)){ | |
var node:Node = onceCheck[fun]; | |
base[node.index] = null; //将值设为null,不使用splice,以免破坏dispatch中的循环操作。 | |
delete onceCheck[fun]; | |
count--; | |
} | |
} | |
/** | |
* 检查是否存在某个方法对象 | |
*/ | |
public function contain(fun:Function):Boolean{ | |
return fun in onceCheck; | |
} | |
/** | |
* 获取监听对象数量 | |
*/ | |
public function get length():int{ | |
return count; | |
} | |
/** | |
* 移除所有监听方法 | |
*/ | |
public function removeAll():void{ | |
for(var fun:* in onceCheck){ | |
remove(fun); | |
} | |
} | |
/** | |
* TODO | |
* @param args | |
*/ | |
public function dispatch(...args):void{ | |
if(isEmpty()){ | |
return; | |
} | |
var len:int = base.length, i:int, actual:int, fun:Function; | |
for(i = 0; i < len; i++){ | |
fun = base[int(i)]; | |
if(fun != null){ | |
if(args.length == 0){ | |
fun(); | |
} | |
else if(args.length == 1){ | |
fun(args[0]); | |
} | |
else{ | |
fun.apply(null, args); //apply有可能会影响性能, 所以判断方法参数长度 | |
} | |
//有可能监听方法中存移除操作破坏了循环, 所以需要判断是否为空 | |
if(base[int(i)] != null){ | |
if(onceCheck[fun].executeOnce){ | |
remove(fun); //if execute once, just remove it | |
} | |
if(actual < i){ | |
base[int(actual)] = fun; | |
onceCheck[fun].index = actual; | |
base[int(i)] = null; | |
} | |
actual++; | |
} | |
} | |
} | |
if(i != actual){ | |
len = base.length; | |
while(i < len){ | |
if(base[int(i)] != null){ | |
base[int(actual)] = base[int(i)]; | |
onceCheck[base[int(actual)]].index = actual; | |
base[int(i)] = null; | |
actual++; | |
} | |
i++; | |
} | |
base.length = actual; | |
} | |
} | |
/** | |
* 检查是否该Signal对象内部存储结构为空 | |
*/ | |
public function isEmpty():Boolean{ | |
return count == 0; | |
} | |
/** | |
* 获取指定function对象的索引 | |
* @param fun | |
*/ | |
public function getIndex(fun:Function):int{ | |
if(contain(fun)){ | |
return onceCheck[fun].index; | |
} | |
return -1; | |
} | |
} | |
} | |
/** | |
* 记录方法对象在数组中的索引和"是否执行一次即删除"的节点对象 | |
*/ | |
internal class Node{ | |
public var executeOnce:Boolean = false; | |
public var index:int = -1; | |
public function Node(once:Boolean, index:int):void{ | |
this.executeOnce = once; | |
this.index = index; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
i was trying to understand the comments but failed