如何使用Spring ActionScript中的EventBus

riadevID: 

首先说起EventBus,有过框架使用经验的朋友应该不会陌生。EventBus提供了一种有效的事件托管机制,以解决我们在项目开发中遇到的事件触发与捕获方面的困扰:

  1. 基于Flash Player的事件冒泡机制严重依赖显示列表,在MVC架构中,很多类并非显示类,难以依赖冒泡机制。
  2. 如何在各个类之间简单高效的传递事件,而又要尽量避免高耦合,是个难以解决的问题。

Spring ActionScript中也提供了EventBus的机制,而且它可以结合Metadata Tag实现事件托管,尽量维持代码编写的优雅。让我们来看一个简单的例子:

首先我们需要在XML配置中增加两个对象,它们将完成事件托管的功能实现。EventHandlerMetaDataPostProcessor类将根据Metadata标注确认哪些方法将用于事件侦听,而RouteEventsMetaDataPostProcessor将完成事件托管,即委托托管的类派发的事件交由EventBus处理

  1. <objects>
  2.  
  3. <object id="a" class="test.A"/>
  4. <object id="b" class="test.B"/>
  5. <!--EventBus-->
  6. <object id="eventhandlerProcessor" class="org.springextensions.actionscript.ioc.factory.config.EventHandlerMetaDataPostProcessor"/>
  7. <object id="routeEventsProcessor" class="org.springextensions.actionscript.ioc.factory.config.RouteEventsMetaDataPostProcessor"/>
  8.  
  9. </objects>

然后我们在主代码中加载配置文件,这个过程与我们之前使用Spring ActionScript的方式相同:

  1. package
  2. {
  3. import flash.display.DisplayObject;
  4. import flash.display.Sprite;
  5.  
  6. import org.springextensions.actionscript.context.support.XMLApplicationContext;
  7.  
  8. import test.ClassRef;
  9.  
  10. public class EventBusTest extends Sprite
  11. {
  12. [Embed(source="config/application_context.xml",mimeType ="application/octet-stream")]
  13. public var view:Class;
  14.  
  15. public var applicationContext:XMLApplicationContext;
  16.  
  17. public function EventBusTest()
  18. {
  19. new ClassRef;
  20. applicationContext = new XMLApplicationContext();
  21. applicationContext.addEmbeddedConfig(view);
  22. applicationContext.load();
  23. addChild(applicationContext.getObject("a") as DisplayObject);
  24. addChild(applicationContext.getObject("b") as DisplayObject);
  25. }
  26. }
  27. }

然后有两个类A和B,注意A中将派发事件,交由EventBus托管,EventBus将执行B中的Handler,执行相应的操作,整个过程非常优雅的实现了松耦合,A和B彼此都不知道对方的存在,甚至也不需要知道EventBus的存在。

A的代码,注意我们使用了[RouteEvents]来标注哪些事件将被托管:

  1. package test
  2. {
  3. import flash.display.Sprite;
  4. import flash.events.MouseEvent;
  5.  
  6. [RouteEvents]
  7. [Event(name="move",type="test.TestEvent")]
  8.  
  9. public class A extends Sprite
  10. {
  11.  
  12. public function A()
  13. {
  14. super();
  15. this.graphics.beginFill(0x000000,1);
  16. this.graphics.drawRect(0,0,100,100);
  17. this.graphics.endFill();
  18. x = 10;
  19. y = 10;
  20. addEventListener(MouseEvent.CLICK,startMove);
  21. }
  22.  
  23. private function startMove(e:MouseEvent):void {
  24. trace("A clicked");
  25. var sEvt:TestEvent = new TestEvent(TestEvent.MOVE);
  26. sEvt.speed = 10;
  27. dispatchEvent(sEvt);
  28. }
  29.  
  30. }
  31. }

B的代码,注意我们使用了[EventHandler(name="move")]来确定哪个事件将被后面的方法处理,注意该方法必须是Public的:

  1. package test
  2. {
  3. import flash.display.Sprite;
  4.  
  5. public class B extends Sprite
  6. {
  7. public function B()
  8. {
  9. super();
  10. this.graphics.beginFill(0xFF0000,1);
  11. this.graphics.drawRect(0,0,100,100);
  12. this.graphics.endFill();
  13. x = 110;
  14. y = 10;
  15. }
  16.  
  17. [EventHandler(name="move")]
  18. public function trackHandler(e:TestEvent):void {
  19. x += e.speed;
  20. trace("B move:"+e.speed);
  21. }
  22.  
  23. }
  24. }

项目源码查看

详情请点击这里查看

您给予的分值: None 平均分: 4 (1 vote)

这个比起parsely,功能

这个比起parsely,功能有点弱。
小项目很顺手,楼主有用这个在比较大的项目中吗,你们是怎么解决大量视图在spring里面初始化的时候让flashplayer假死的问题的。那么多视图,光反射和查找这些meta就要很多计算资源的。
如果spring不能提供一个类似prsely的绑定已有视图的功能,估计还是不可能大规模应用吧。

其实这个spring也有这

其实这个spring也有这方面的功能。 关于大规模视图的初始化,一般做法是让视图内容自己初始化。然后,通过搜索已有的视图,将他们也纳入到ioc容器里面。
parsely也是这么做的,不过,我觉得spring使用stage wiring来实现的。他的文档不如parsely详细。说得没有那么细节。这个可能是spring的一个问题也算是。

这个其实有个需要细心的地方

自定义的meta其实比较烦人。
你一不小心忘掉了,测试N天也查不到原因!
我觉得还是应该写一个自己的代码来确保所有的需要的menta都编译进去了,否则就再启动的时候抛出个异常。这样能提醒你编译参数需要配置

不过,看来riameeting开始向高端内容进军了,不错,这个文章可以把我们部门的人叫来看看。

抱歉原文漏了Metadata的

抱歉原文漏了Metadata的配置,确实需要务必在编译参数中加上:
-keep-as3-metadata+=EventHandler,RouteEvents
这是很容易犯的错误,而且难以调试

发表新评论

  • 网页地址和电子邮件地址将会被自动转换为链接。
  • 行和段被自动切分。
  • 您可以使用下面的标签来高亮显示您的评论内容: <code>, <blockcode>. 可以使用"[foo]".旁边显示标签样式 "<foo>" PHP代码可以用这样的区块来包含<?php ... ?> or <% ... %>

更多格式化选项信息

验证区域
系统验证:请回答下面的问题