Signals框架介绍(一)基本用法

注意:本文参考An introduction to AS3 Signals写成,但不是翻译,有增删改。

Signals是一个基于AS3的轻量级事件框架,它被设计用来代替AS3内置的Event框架。

为什么我们要放弃Event框架,改用Signals呢?原因主要有以下几点:

  1. 使用AS3内置的Event框架,必须继承EventDispatcher或者自行实现IEventDispatcher,而Signals使用组合,可以避免继承;
  2. 使用AS3内置框架在事件中实现值的传递,必须自定义事件类才可以。而Signals可以方便的实现多个强类型值的传递;
  3. Signals不使用字符串来区分不同的事件,而是使用实例;
  4. Signals的速度更快,据说是AS3内置事件机制的4倍。

来看个简单的例子吧,这个例子中的闹钟会叫我们起床。此范例部分源码来自An introduction to AS3 Signals

基本用法

先看看闹钟类AlarmClock.as

 1package
 2{
 3import org.osflash.signals.Signal;
 4
 5/**
 6* Signals闹钟范例
 7* @author Aiden Tailor(http://www.developria.com/2010/10/an-introduction-to-as3-signals.html)
 8* @author zrong(zengrong.net)
 9*/
10
11public class AlarmClock
12{
13	public function AlarmClock()
14	{
15		alarm = new Signal();
16	}
17
18	/**
19	 * 声明一个Signal实例用来发送Signal
20	 */
21	public var alarm:Signal;
22
23	public function ring():void
24	{
25		//发布闹钟的响铃事件
26		alarm.dispatch();
27	}
28}
29}

再来看看起床类Wakeup.as

 1package
 2{
 3import flash.display.Sprite;
 4
 5[SWF(width=500,height=300,frameRate=30,backgroundColor=0xFFFFFF)]
 6/**
 7 * 测试闹钟
 8 * @author Aiden Tailor(http://www.developria.com/2010/10/an-introduction-to-as3-signals.html)
 9 * @author zrong(zengrong.net)
10 */
11public class Wakeup extends Sprite
12{
13	public function Wakeup()
14	{
15		_alarm  = new AlarmClock();
16
17		//向alarm注册事件,这里不需要提供任何的事件名称。因为alarm就是一个确定的Signal实例。
18		_alarm.alarm.add(handler_ring);
19
20		//使用addOnce,让alarm在事件收到一次后立即取消
21		//_alarm.alarm.addOnce(handler_ring);
22
23		_alarm.ring();
24		_alarm.ring();
25	}
26
27	private var _alarm:AlarmClock;
28
29	/**
30	 * 由于我们并没有在事件中传递参数,因此这里的方法也不需要提供任何参数。
31	 */
32	private function handler_ring():void
33	{
34		trace('起床了!!!');
35	}
36}
37}

在进行事件注册的时候,我们使用的是AlarmClock的public属性alarm。在面向对象编程中,这种方式是不可取的。但我们现在只是个范例对么?不要要求那么严格好不好?

当然,如果你知道在AS3中,使用get方法会比直接使用public属性的性能低不少,或许你也会让这种“不规范”的编程方法延续下去?

###取消事件注册

如果运行这个范例,应该可以看到2条“起床了!!!”的trace信息。然后,取消addOnce一行的注释,并注释掉add那行,让它们变成这样:

 1public function Wakeup()
 2{
 3	_alarm  = new AlarmClock();
 4
 5	//向alarm注册事件,这里不需要提供任何的事件名称。因为alarm就是一个确定的Signal实例。
 6	//_alarm.alarm.add(handler_ring);
 7
 8	//使用addOnce,让alarm在事件收到一次后立即取消
 9	_alarm.alarm.addOnce(handler_ring);
10
11	_alarm.ring();
12	_alarm.ring();
13}

再次运行范例,应该只能看到1条trace信息了。你可以把这种现象理解成原来的AS事件机制中的removeEventDispatcher被自动执行了。

当然,手动移除也是可以的。如果你使用的是add方法注册,可以使用下面的方法来移除事件的注册。

1_alarm.alarm.remove(handler_ring);
2_alarm.alarm.removeAll();

###传递参数

看看传递参数有多简单吧……修改AlarmClock.as中的相关代码:

 1public function AlarmClock()
 2{
 3	//让我们传递一个AS3的标准Date对象吧,让那个懒虫知道现在几点
 4	alarm = new Signal(Date);
 5}
 6
 7public function ring():void
 8{
 9	//把当前的时间发出去
10	alarm.dispatch(new Date());
11}

再修改Wakeup.as中的相关代码:

1private function handler_ring($date:Date):void
2{
3	trace('起床了!!!也不看看几点了:'+$date.toString());
4}

就这样,不需要该死的继承Event和重写clone()了,是不是很清净呢?