AS3 Signals
在项目中,使用as3内置事件框架必须通过自定义事件才可以实现值的传递,大量自定义事件、定义常量和整个事件派发的管理、添加侦听器、移除侦听器,或多或少都会带来大量的代码,而signals这个框架思想原来在C#中原本就有,作者整合了C#中的signals思想,实现起来比as3内置的事件更快捷,可以很轻松的实现多个强类型值的传递,的在一定程度上也会简化很多代码。有朋友测试,signals里面用内置的事件竟然是as3内置事件运行速度的4倍。
但是我想大家已经对Event事件机制已经非常熟悉了,那么我们就从Event框架机制开始吧。
var sprite:Sprite = new Sprite() sprite.addEventListner(MouseEvent.CLICK, onEventHandler) function onEventHandler(me:MouseEvent):void { //执行代码 }
稍微解释一下,以方便理解Signals框架,首先定义一个Sprite的实例,使用addEventListener()方法为sprite添加事件侦听,事件类型是MouseEvent.CLICK事件,事件响应函数为onEventHandler函数。如果想使用AS3.0 Event框架来自定义事件那绝对是个体力活,但使用Signals框架来自定义却非常简单。首先从最基本的开始。
Signal类
AlarmClock.as
这个类用来定义一个AlarmClock,同时使用Signals框架自定义事件以被AlarmClock的实例来捕获。
package insideria.basicSignal { import org.osflash.signals.Signal; public class AlarmClock { //定义一个alarm事件,设定为public属性以被访问,相当于Event框架中所使用的MousEvent.CLICK public var alarm:Signal; public function AlarmClock() { //实例化alarm alarm = new Signal(); } public function ring():void { //调用Signal类的实例的方法dispatch(),只要该方法被执行,Signal就会派发alarm事件,我们要做的就是捕获该事件,并作出相应 alarm.dispatch(); } } }
WakeUp.as
主函数类文档
package insideria.WakeUp { import flash.display.Sprite; public class WakeUp extends Sprite { //定义一个AlarmCLock类的变量 private var alarmClock:AlarmClock; public function WakeUp() { //实例化Alarmclock alarmClock = new AlarmClock(); //使用signal的add()方法为该实例的alarm事件添加一个响应函数。类似于addEventListner()方法 alarmClock.alarm.add(onRing); //调用ring()方法执行signal的dispatch()方法,派发事件 alarmClock.ring(); } //alarm事件的响应函数 private function onRing():void { trace("Wake up!"); } } }
执行文档在输出面板就会看到:
Wake Up!
如果想在使用Signal定义事件时想要派发参数也可以
AlarmClock.as
package insideria.basicSignalArguments { import org.osflash.signals.Signal; public class AlarmClock { public var alarm:Signal; public function AlarmClock() { alarm = new Signal(String); } public function ring():void { alarm.dispatch("9 AM"); } } }
当然多类型的参数也是可以的,只要在dispatch()方法里依次输入对用类型的数值即可
alarm = new Signal(String, Number, int, uint, Boolean); alarm.dispatch("9 AM", 45.4, -10, 5, true);
WakeUp.as
package insideria.basicSignalArguments { import flash.display.Sprite; public class WakeUp extends Sprite { private var alarmClock:AlarmClock; public function WakeUp() { alarmClock = new AlarmClock(); alarmClock.alarm.add(onRing); alarmClock.ring(); } private function onRing(time:String):void { trace("Wake up! It's already " + time); } } }
测试影片可以看到输出面板输出:
Wake Up! It's already 9 AM
还记得在as3.0 Event框架下,我们每次添加事件都要使用removeEventListner()方法来移除事件,Signal提供addOnce()方法仅添加一次事件而不需要我们再去添加额外代码去移除事件,在事件被派发一次后自动移除该事件。
alarmClock.alarm.addOnce(onRing);
当然在更多情况下我们还是想要手动控制事件的移除,你可以使用remove()方法去移除事件,或者使用removeAll()方法一次性移除所有事件。
alarmClock.alarm.remove(onRing); alarmClock.alarm.removeAll();
在as3.0 Event框架下,事件提供了currentTarget/Target用来通过事件来访问对象,Signlas框架也提供了类似的属性。
DeluxeSignal
DeluxeSignal类与GenericEvent类共同使用可以实现上述用法
AlarmClock.as
package insideria.deluxeSignal { import org.osflash.signals.DeluxeSignal; import org.osflash.signals.events.GenericEvent; public class AlarmClock { //定义alarm事件 public var alarm:DeluxeSignal; //定义一个字符串 public var message:String; public function AlarmClock() { //实例化DeluxeSignal alarm = new DeluxeSignal(this); //为字符串赋值 message = "This is a message from our AlarmClock"; } public function ring():void { //绑定派发事件 alarm.dispatch(new GenericEvent()); } } }
WakeUp.as
package insideria.deluxeSignal { import org.osflash.signals.events.GenericEvent; import flash.display.Sprite; public class WakeUp extends Sprite { private var alarmClock:AlarmClock; public function WakeUp() { alarmClock = new AlarmClock(); alarmClock.alarm.add(onRing); alarmClock.ring(); } private function onRing(event:GenericEvent):void { trace(event.target); trace(event.signal); trace(event.target.message); } } }
测试影片,输出面板输出:
alarmClock
DeluxeSignal
This is a message from our AlarmClock
NativeSignal
最后Signals框架提供NativeSignal类用来代替Event框架事件,以MouseEvent为例
//自定义事件clicked private var clicked:NativeSignal; private var box:Sprite; box = new Sprite(); box.graphics.beginFill(0xCCCCCC); box.graphics.drawRect(0, 0, 100, 100); box.graphics.endFill(); addChild(box); //通过Event机制下的MouseEvent.CLICK,为box添加clicked事件 clicked = new NativeSignal(box, MouseEvent.CLICK, MouseEvent); //添加响应函数 clicked.add(onClicked); private function onClicked(event:MouseEvent):void { trace("clicked"); }
再来个例子:
package com.pleribus.as3signalsdemo { import org.osflash.signals.natives.NativeSignal; import org.osflash.signals.Signal; import flash.display.Sprite; import flash.events.MouseEvent; /** * @author Clint Hannaford */ public class Player extends Sprite { public var playerKilled:Signal; public var playerHit:Signal; public var click : NativeSignal; private var health: Number; public function Player(){ } public function init() : void { //为health变量赋值 health = 10; //实例化自定义事件playerKilled playerKilled = new Signal(); //实例化自定义事件playerHit playerHit = new Signal(); //实例化自定义事件click click = new NativeSignal(this, MouseEvent.CLICK, MouseEvent); //为此类画上图形按钮 with (this.graphics){ beginFill(0x000000); drawRect(0, 0, 50, 50); endFill(); beginFill(0xFFFFFF); drawRect(10, 10, 10, 10); drawRect(30, 10, 10, 10); drawRect(10, 30, 30, 10); } } //自定义一个公有方法hit public function hit():void{ //health变量自减 health--; //为此类的实例绑定并派发playerHit事件 playerHit.dispatch("Player Hit", health); //判断health变量值,当小于等于0时执行kill()函数 if (health <= 0){ kill(); } } //私有方法kill,执行此函数为此类的实例绑定并派发playerKilled事件 private function kill():void{ playerKilled.dispatch("Player Killed"); } } }
package com.pleribus.as3signalsdemo { import flash.events.MouseEvent; import flash.text.TextField; import flash.display.Sprite; /** * @author Clint Hannaford */ public class SignalsDemo extends Sprite { public var player:Player; public var textOutput:TextField; public function SignalsDemo() { //执行addPlayer()方法 addPlayer(); //执行addTextField()方法 addTextField(); //为自定义事件添加响应函数 player.playerHit.add(onPlayerHit); player.playerKilled.add(onPlayerKilled); player.click.add(onClickPlayer); } //实例化Player类 private function addPlayer():void{ player = new Player(); player.init(); player.x = 30; player.y = 30; player.buttonMode = true; addChild(player); } //实例化TextField private function addTextField():void{ textOutput = new TextField(); textOutput.x = 10; textOutput.y = 100; textOutput.width = 350; textOutput.height = 200; textOutput.border = true; addChild(textOutput); } //事件响应函数 private function onClickPlayer(event:MouseEvent) : void { // 每当按钮被点击时执行Play()类中定义的hit()方法 player.hit(); } private function onPlayerKilled(message:String) : void { textOutput.appendText(message+"\n"); player.playerHit.remove(onPlayerHit); player.playerKilled.remove(onPlayerKilled); player.click.remove(onClickPlayer); this.removeChild(player); } private function onPlayerHit(message:String, health:Number) : void { textOutput.appendText(message+" - health now: "+health+"\n"); } } }