AS3事件处理模型--转自N神

AS3事件处理模型
[ 2006-09-14 14:15:25 | 发布: N神 ]
字体大小: | |
一直忙,却不知道在忙啥,难得有空自己看看这部分内容,分享一下

以前的事件处理模型:
on() 在 Button 或 MovieClip上的
onClipEvent() 直接写在 MovieClip instances 上的
Callback 函数 例如XML.onload 和 Camera.onActivity
addListener()方法 简单的事件监听
The UIEventDispatcher class 实现了部分 DOM event model.

as3有什么不同:

全部废除,只有addEventListener()一种了
listener只可以是methods或function,而且自带了Delegate(好多资料里都有写,这点就不讨论了)
多了event flow概念,就是说as2中只有广播者才能addEventListener,as3中即使object不发广播,只要它在event flow中都可以 addeventlistener

event flow:

事件源如果不在displaylist中,那么跟as2一样只能 事件源.addEventListner("xxx" xxxfunc)

否则如果事件源是可视的,那么Flashplayer会把这个event object扔到事件源所处的displaylist中去

displaylist 是一个树型结构,可以想象为下图

attachments/200609/14_141752_1.jpg


,然后这个eventObject会自己旅游到事件源那去,然后再回来

event flow 就是描述eventObject在这个displaylist中的旅游过程

顶端是一个特殊的display object容器---- Stage,他表现在flash.display.Stage类中,然后每一个display object都有一个属性叫stage 都引用这个应用程序的Stage

event flow 概念上被分为3部分。

第一部分叫 capture 阶段 包括从Stage到目标的parent
第2 部分叫 target 阶段 就只有目标节点
地3 部分叫 bubbling 阶段 包括从目标的parent到Stage

如图:

attachments/200609/14_150248_2.jpg


前边说过如果事件源不在displaylist中,那么跟as2一样只能 事件源.addEventListner("xxx" xxxfunc) 因为它就只参加 target阶段,1,3阶段都不参与
一些特殊的事件也是这样,例如enterFrame 和 init

否则该eventObject将参与这3个阶段

但在一般情况下,默认的addEventListener只监听event flow第 2,3阶段。

看个鼠标点击的例子 (点此下载)

mc里放mc1,点击mc1
mc.addEventListener("click",func)
function func(e){
  trace(e.target.name,"------",e.currentTarget.name)
  trace("e.eventPhase",e.eventPhase)
  }

/*----------------------out put----------
 mc1 ------ mc
 e.eventPhase 3
---------------------------------------*/

e.eventPhase返回 1,2或3,分别代表上边说的3个阶段, 上边的意思就是在event flow第3个阶段捕捉到的这个事件

流程是这样滴:

当你点mc1 目标节点就被设置为mc1

然后Flashplayer 就扔出一个eventobject到Stage

这个eo落地就开始跑,这个跑道就是Stage---> mc1 ---->Stage 这一圈

整个跑道会经过两次mc ,Stage---> mc1 经过一次 ,然后mc1 ---->Stage又经过一次,也就是第1阶段和第3阶段

mc.addEventListener("click",func) 默认只监听第2,3阶段,而经过mc的只有1,3阶段,所以这句话就是在整个跑道上第3阶段mc位置放个路障

eo向mc1跑, 然后从mc1返回Stage的徒中经过mc时候碰到了路障触发了这个事件,所以e.eventPhase显示是第3阶段 目标是mc1,路障是mc

如果想第一阶段就捕捉事件怎么做?

加个参数true,代表只捕捉第一阶段的事件
mc.addEventListener("click",func,true)
function func(e){
  trace(e.target.name,"------",e.currentTarget.name)
  trace("e.eventPhase",e.eventPhase)
  }

/*----------------------out put----------
 mc1 ------ mc
 e.eventPhase 1
//---------------------------------------*/

看,第一阶段就被障碍拦住了吧

如果想3个阶段都兼听呢?

麻烦点,得add两次了,设两个路障了
mc.addEventListener("click",func,true)
mc.addEventListener("click",func)
function func(e){
  trace(e.target.name,"------",e.currentTarget.name)
  trace("e.eventPhase",e.eventPhase)
  }
/*----------------------out put----------
 mc1 ------ mc
 e.eventPhase 1
 mc1 ------ mc
 e.eventPhase 3
---------------------------------------*/

阻止event flow !

设个障碍还不行,还要阻止?
mc.addEventListener("click",func,true)
mc.addEventListener("click",func)
function func(e){

  trace(e.target.name,"------",e.currentTarget.name)
  trace("e.eventPhase",e.eventPhase)
  e.stopPropagation()
  }

/*----------------------out put----------
 mc1 ------ mc
 e.eventPhase 1
---------------------------------*/

怎么样只捕捉了第1个阶段吧,

其实有两个方法可以阻止event flow,

e.stopPropagation()
e.stopImmediatePropagation()

区别就在于一个影响当前节点一个不影响当前节点的其他listener,具体看下边的例子
mc.addEventListener("click",func,true)
mc.addEventListener("click",func)
mc.addEventListener("click",func2,true)
mc.addEventListener("click",func2)

function func(e){
e.stopPropagation()
//e.stopImmediatePropagation() //换换看看区别
  trace(e.target.name,"------",e.currentTarget.name)
  trace("e.eventPhase",e.eventPhase)
}
function func2(e){

  trace(e.target.name,"--22222--",e.currentTarget.name)
  trace("2222222e.eventPhase",e.eventPhase)
}

优先级(Event Priority)

同一个事件有很多listeners,这些listeners收到消息也有个先后顺序,顺序默认是你add Listener时的顺序,如下边例子,completeListenerA肯定在completeListenerB 前执行
package {
import flash.display.*;
import flash.net.*;
import flash.events.*;
public class FileLoader extends Sprite {
public function FileLoader ( ) {
var urlLoader:URLLoader = new URLLoader( );
// Registration order determines execution order
urlLoader.addEventListener(Event.COMPLETE, completeListenerA);
urlLoader.addEventListener(Event.COMPLETE, completeListenerB);
urlLoader.load(new URLRequest("someFile.txt"));
}
private function completeListenerA (e:Event):void {
trace("Listener A: Load complete");
}
private function completeListenerB (e:Event):void {
trace("Listener B: Load complete");
}
}
}

但是这个顺序是可以改变的,这就是我们的优先级要做的了。

addEventListener(type, listener, useCapture, priority, useWeakReference)

优先级默认是0 ,优先级越大,越先收到到广播。

下边的例子强行指定completeListenerB在completeListenerA之前执行
package {
import flash.display.*;
import flash.net.*;
import flash.events.*;
public class FileLoader extends Sprite {
public function FileLoader ( ) {
var urlLoader:URLLoader = new URLLoader( );
// Priority parameter determines execution order
urlLoader.addEventListener(Event.COMPLETE,
completeListenerA,
false,
0);
urlLoader.addEventListener(Event.COMPLETE,
completeListenerB,
false,
1);
urlLoader.load(new URLRequest("someFile.txt"));
}
private function completeListenerA (e:Event):void {
trace("Listener A: Load complete");
}
private function completeListenerB (e:Event):void {
trace("Listener B: Load complete");
}
}
}

优先级很有用,比如可以设置一个高优先级的listener来初始化应用程序,使其他listener在初始化之前没有机会执行
或者用高优先级的listener来阻止事件发送,使其他listener接收不到

虽然优先级很有用,但是一定要尽量不用,因为优先级是可变的,你依赖他的执行顺序会使得代码它difficult to maintain,and make source
code more difficult to follow.

弱引用:

The concept of weak references is particularly useful when adding listeners to objects. To understand why weak references are so good, you first need to understand a little about garbage collection. Garbage collection is how Flash Player cleans up memory that isn't needed anymore; it's important because otherwise applications would use more and more RAM until they required the system to restart. Flash Player 9 uses two systems called reference counting and mark and sweep.

Reference counting is not new to Flash Player. It is the traditional way in which Flash Player has run garbage collection. When you create an object in ActionScript, that object exists in memory. However, the object is useful only as long as there are references (such as variables) to that object. When no more references exist, it is safe to assume that the object is no longer used and can be garbage collected. Although this system is efficient, it is not accurate because it is possible, through circular references, to have references still in existence even though none of the references is actually accessible. For example, two objects can have references to one another. If the references to those objects are deleted, we would expect that the objects themselves would be garbage collected. However, because they have references to one another, they remain in memory.

The mark-and-sweep garbage collection system solves the circular reference problem by traversing all active (accessible) nodes within an application. Any objects that exist outside of the active nodes can be assumed to be no longer in use, and they can be garbage collected.

Although the two garbage collection systems work in conjunction to efficiently and effectively manage memory usage, they do not compensate for incorrect programming. It's important that you always remove event listeners when you no longer need to use them. If you register an event listener using normal references, it will not get garbage collected even if you delete the listener or the object containing the listener because the event dispatcher will still have a reference to it. Removing the event listener using removeEventListener() ensures that the event target no longer has a reference to the listener, and that action will allow it to be properly garbage collected after you've deleted the listener.

However, sometimes we can't remove the listeners because our object is deleted elsewhere. This is where weak references come in handy. They allow for normal event listening functionality, but when the listener object is removed, the listener is removed from memory properly because the reference is weak and not counted by the reference counting function of the garbage collector.

You can specify that a listener should use a weak reference by registering it using a value of true for the fifth parameter to the addEventListener() method.

target.addEventListener(MouseEvent.CLICK, onClick, false, 0, true);

阻止事件默认行为(preventDefault)

有些事件有默认的行为,我们可以阻止这些默认行为,例如下边的TextEvent.TEXT_INPUT事件发生时我们阻止了 字母显示在文本框里这一默认行为,而把x放了进去
package {
import flash.display.*;
import flash.text.*;
import flash.events.*;
// Changes all user-entered text to the character "x"
public class InputConverter extends Sprite {
private var t:TextField;
public function InputConverter ( ) {
// Create the text field
t = new TextField( );
t.border = true;
t.background = true;
t.type = TextFieldType.INPUT
addChild(t);
// Register for the TextEvent.TEXT_INPUT event
t.addEventListener(TextEvent.TEXT_INPUT, textInputListener);
}
// Listener executed when the TextEvent.TEXT_INPUT event occurs
private function textInputListener (e:TextEvent):void {
// Show what the user tried to enter
trace("Attempted text input: " + e.text);
// Stop the user-entered text from appearing in the text field
e.preventDefault( );
// Add the letter "x" to the text field instead of
// the user-entered text
t.appendText("x");
}
}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
【优质项目推荐】 1、项目代码均经过严格本地测试,运行OK,确保功能稳定后才上传平台。可放心下载并立即投入使用,若遇到任何使用问题,随时欢迎私信反馈与沟通,博主会第一时间回复。 2、项目适用于计算机相关专业(如计科、信息安全、数据科学、人工智能、通信、物联网、自动化、电子信息等)的在校学生、专业教师,或企业员工,小白入门等都适用。 3、该项目不仅具有很高的学习借鉴价值,对于初学者来说,也是入门进阶的绝佳选择;当然也可以直接用于 毕设、课设、期末大作业或项目初期立项演示等。 3、开放创新:如果您有一定基础,且热爱探索钻研,可以在此代码基础上二次开发,进行修改、扩展,创造出属于自己的独特应用。 欢迎下载使用优质资源!欢迎借鉴使用,并欢迎学习交流,共同探索编程的无穷魅力! 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip 基于业务逻辑生成特征变量python实现源码+数据集+超详细注释.zip
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值