一. 事件机制
1. as常见而且内建的解耦机制,解决以下问题
a) 传统回调机制只能一对一,产生强耦合
b) 传统机制使用不统一的方式处理不同对象的异步操作
2. actionscript使用事件派发器EventDispatcher类实现事件派发,通常包括三对象
a) 事件对象通常是Event的子类,用于指定监听事件类型(通常是常量字符串成员)和作为监听器的参数传入(函数参数,通过它获取上下文信息实现解耦)。
b) 事件派发器在监听器中被成为target,是广播事件的对象,支持多监听器注册addEventListener。在监听器中有两种获取方式:currentTaget和target,currentTaget是开始时调用addEventListener注册事件对象,target则是处于事件真正发生的对象
c) 监听器。可以是成员函数,也可以是匿名函数,是处理事件的逻辑部分
3. 注册和删除事件。一般习惯是addEventListener和removeEventListener需要成对出现。个人认为即使不必要,但最好这么做。由于涉及gc回收,一些匿名监听器在addEventListerner中指定弱引用(由as负责释放)
4.AddEventListener的参数解析:
a)事件类型:一般是事件对象对应的字符串常量,与监听器的参数对应。例如Event.COMPLETE后的监听器的参数就是e:Event。
b)监听器:一般是成员变量,解决派发器与监听器之间的引用问题(监听器不会被无端端地GC掉),但如果是匿名函数,将因为与注册者存在引用而无法gc掉注册者和监听器。
c)在哪个阶段调用监听器函数:有几种情况(假设this是m_object的显示容器)
其一:this.addEventListener(xx, xx)冒泡阶段,所有发生在自己和addChild的显示对象(如果是ui事件)的事件都触发监听器。在监听器中target是发生事件的对象,而currentTarget是this(容器自身)
其二:m_object.addEventListener(xx,xx)目标阶段,也是最常见的用法,用于响应m_object的事件,而不会让其父容器听到(如果是ui事件)。此时target==currentTarget
其三:this.addEventListener(xx,xx,true)捕获阶段, 从显示对象的根向目标方向遍历执行监听器,但不会到达目标和向上冒泡。较少用,要用的话一般在监听器中使用stopImmediatePropagation让事件仅由容器this来响应
其四:同时使用this.addEventListener(xx, xx)和this.addEventListener(xx,xx,true),可以同时监听捕获和冒泡目标的事件。
d)优先级,用于决定哪个监听器函数先调用,一般不用(因为默认使用目标阶段,较少出现同一种事件注册多个不同的监听器)
e)弱引用,用于那些无法正常removeEventListener的情况(例如注册对象被赋值为null失去引用)。缺点是弱引用无法控制其失去监听能力的时机。另一种情况,你希望监听器被gc(例如你不停地注册匿名监听器而不removeListener,导致大量的匿名函数不被gc,因为有引用存在)如果你习惯用成员函数作监听器,推荐用removeListener(立刻生效,不像弱引用那样)当然你监听ui事件而且是子级显示对象例如this.button.addEventListerner,但button突然被赋值为null导致不能removeListener,可以考虑用弱引用(一般没必要,因为this的外部引用不会在事件发生的时候被赋值为null被gc掉,况且this会和成员函数一起被gc。this.button也一般不会被赋值为空。即便你要让this.button=null,你也有机会在此之前使用removeListener,除非你懒得去做)
补注:个人认为(不一定正确),在这种场合使用弱引用:
* 你的事件不是添加在自己或成员对象上(最常见的是对stage添加键盘事件)
* 你的事件不是注册到当前类的成员函数(最常见的是匿名闭包)
* 你的事件不知道在什么时候remove(例如你不是用对称的方式添加删除事件)
有些特殊情况(好像?)不应该使用弱引用
* 用Event.ADDED_TO_STAGE和Event.REMOVED_FROM_STAGE的响应函数中对称地添加删除事件(未验证)
* 有些事件如果只允许发生一次(你希望你的响应函数要么不执行,要么就只执行一次),你可以立刻在响应函数中删除这个事件,例如在构造函数中:
addEventListener(Event.ADDED_TO_STAGE, onAdd);
因为即便Event.ADDED_TO_STAGE被派发多于一次,
也不会影响逻辑(因为你就是希望onAdd仅执行一次,除非对象被释放)
* 有些事件所添加的对象和注册函数都是持久的,
就可省略事件的删除,例如文档类的单实例对象、stage以及它们的成员函数。
二 GC机制
由于fp的GC向来都是写as的人诟病对象,所以大多数人都会想尽办法去防止代码中出现内存泄漏的情况(因为fp会因为内存太大而崩溃)虽说这不是什么好事(很多语言都竭力让程序员不用考虑或者提供API应付这个问题,但是as就是不让你控制),一些GC问题实际上迫使程序员改良代码以提高as运行的效率和稳定性,甚至可以让代码更有条理。
1. fp9的MouseEvent.CLICK问题。从我测试看来,似乎fp9的内存回收特别慢,尤其是当你想用MouseEvent.CLICK去释放某个显示对象的时候(详细请参考http://joshblog.net/2009/04/30/combine-buttonmode-true-and-a-mouse-click-to-leak-memory/)可喜的是这个貌似bug的问题到了fp10就没了。虽说可以用buttonMode = false去解决这个无法gc的恐怖bug,但个人尝试觉得最好用MouseEvent.MOUSE_DOWN代替(MOUSE_UP也会导致这个bug出现)结论是,要么大家都升级到fp10,要么就别用这个让人困惑的CLICK事件。
2. fp10的gc速度比fp9快。目前看来似乎是这样(估计快10倍)但内存承载能力就差不多(估计底层没有改什么)而且内存负载能力似乎跟系统物理内存大小有关(?)
三、序列化机制
广泛用于网络协议的实现(因为网络通信通常是流式)
1. 预先序列化:把某种没有结构的数据直接传递给模型对象(可能是构造函数),对于复杂的数据尤其有用。这种序列化很常见,例如使用XMLSocket通信,获取的data可以直接转换为XML对象。另外,as的Socket支持AMF对象的直接传递,这点颇像Java的序列化。常见的有XMLSocket,XML字符串,JSON字符串等。
2. 惰性序列化:惰性序列化并不是说懒人用的,相反这种序列化消耗更多的时间,代码量更大。它适合于不复杂的数据。宗旨是根据要求序列,通过一系列的getter和setter(或者属性赋值)把数据转移到另一个对象。另外,这种机制支持伪的数据域(就是说通过计算获得的,而非实际存储的数据)。一般用于Socket, ByteArray,URLStream对象等。
3. 代理序列化:很像惰性序列化,但它是cache加载的,例如模型数据携带原始数据的引用,每次get的时候判断模型数据是否有数据,有就直接取出,没有就读取原始数据。每次set则同时更新模型和原始数据。这种方法对复杂模型(例如xml数据)或者get时加载的数据有效(例如通过http访问rest服务器的数据)。对于简单结构来说,这么做似乎有点不划算了。
4. 反射机制的序列化:指使用文本协议和flash.utils.Proxy实现的惰性序列化。每个get函数将由Proxy的子类通过重载callProperty获取(被统一为字符串参数)。《Actionscript 3 设计模式》一书介绍了这种序列化(它的例子是用http加载数据)详细请看http://rightactionscript.com/aas3wdp/第六章的例子。它可以结合上面提到的多种序列化方法。
四、状态模式
围绕状态常量进行编程的一种模式(例如游戏分加载配置,加载数据,初始化,开始四种状态)一般会派生出以下几种用法:
1. 状态常量:通常是一些字符串或者整数常量。
2. 状态变量:一个记录当前状态值的变量,在状态常量的范围内
3. 循环事件内的状态机:一种典型的情况,在Event.ENTER_FRAME事件监听器中加入switch,通过return保持状态(可以使用if实现轮询),通过为状态变量赋值实现状态改变。执行迁移瞬间的操作(状态变量赋值前)和保持状态的空闲操作(return前)。
4. 状态迁移:虽说是迁移,实际是依赖于状态机的间接迁移(不是立刻发生发生改变,需要等到Event.ENTER_FRAME之类的事件发生)。对于在Event.ENTER_FRAME之类的事件中调用的函数来说,给状态变量赋值都是在状态机内部做(你也可以挪到状态对象里面做,但实际上还是在Event.ENTER_FRAME里做)。不过,状态迁移(状态变量赋值)还可能发生在别的地方,例如一些异步事件,如鼠标,键盘,定时器事件,就不是在状态机里面了。
5. 状态对象:类似与状态变量,但它成了接口。接口的意义在于你可以实现很多个实例类,然后在里面定义状态迁移,以及不同状态下的环境值(如果你在不同状态下读同一类的对象)。通过多态性,你可以写出统一的处理函数。当然,状态对象不是必须有的。
参考资料:
http://rightactionscript.com/aas3wdp/
五 AS3特殊用法摘录:
1. ||=的使用
例如bracket ||= {start: '[', end: ']'};
等效于if(bracket != null) bracket = {start: '[', end: ']'};
参考自:libspark.as3.Dumper
2. arguments.callee
a.addEventListener(Event.COMPLETE, function (event:Event):void{
event.currentTarget.removeEventListener(Event.COMPLETE, arguments.callee);
});
http://www.adobe.com/livedocs/flash/9.0/ActionScriptLangRefV3/arguments.html
用这种方法可以获取当前执行的函数(闭包),无需保存为局部或成员变量。
3. MouseEvent::updateAfterEvent
常常用于鼠标跟随的平滑显示(在鼠标事件内实现):
private function onMove(event:MouseEvent) : void
{
//改变鼠标sprite的x和y值
event.updateAfterEvent();
}
4. DisplayObject::cacheAsBitmap
一个可读写的属性, 提高非动画显示对象的显示速度,消耗内存。
5. 闭包的局部作用域用法
因为ActionScript和旧版的JavaScript一样,不支持局部作用域,如果要保证局部作用域,可以这样写:
package { import flash.display.Sprite; /** * ... * @author */ public class TestClosure extends Sprite { private var time:int = 0; public function TestClosure() { (function():void { trace("time:", time); })(); var time:int = 1; (function():void { var time:int = 2; trace("time:", time); })(); (function():void { trace("time:", time); })(); /** * 输出:0, 2, 1 * */ } } }
注意,如果闭包使用对象属性,可能导致堆栈错误,所以尽量不要在闭包中使用对象属性。
另外,function外的小括号不能省,因为那是用来消除歧义的(和JavaScript一样)。
6. 使用ByteArray.readByte和wirteByte需要小心,
因为处理的都是有符号整数,读取时需要&0xFF,否则uint值会很大。
var test_bytes:ByteArray = new ByteArray(); test_bytes.writeByte(0xFA); test_bytes.position = 0; if (test_bytes.bytesAvailable > 0) { var result:uint = test_bytes.readByte() & 0xFF; trace("result:", result.toString(16)); } test_bytes.position = 0; if (test_bytes.bytesAvailable > 0) { var result2:uint = test_bytes.readByte(); trace("result2:", result2.toString(16)); } //输出 //result: fa //result2: fffffffa
20110304:
上面的代码太麻烦,
ByteArray有一个方法叫readUnsignedByte可以直接读取无符号字节
7. 尽量不要在Socket的构造函数中传入域名和端口号。应该使用connect函数打开端口。
另外不要和Java的Socket混淆,AS3的socket是基于事件的异步操作,
不可立刻读写(不同于Java的阻塞式Socket读写),
而应该使用事件(见Actionscript3语言和组件参考的例子程序)。
20110424:
8. 执行beginBitmapFill后必须drawRect或其它draw操作方可生效,例如
shape02.graphics.beginBitmapFill(bitmap01, null, false, true); shape02.graphics.drawRect(0, 0, bitmap01.width, bitmap01.height); shape02.graphics.endFill();
20110520:
9. AS3的显示对象平滑显示
AS3显示对象系统提供平滑显示(smoothing)的方法,不过仅限于Bitmap(BitmapData也可,不过BitmapData不属于显示列表的管理范围)
Bitmap的局限性在于它仅能应用于Loader和BitmapData,不能对那些使用addChild的显示对象使用draw方法(因为得不到正常的叠加效果)。
也就是说最好对Loader使用Bitmap,然后对Bitmap使用smoothing,以达到平滑效果,
下面的代码假设Loader已经完成对图像文件的加载:
/** * 必须在Loader完全加载完后才可用 * @param container * @param layer * @param alphaLayer */ private static function addAlphaChild(container:DisplayObjectContainer, layer:Loader, alphaLayer:Loader = null):void { var sprite:Sprite = new Sprite(); sprite.blendMode = BlendMode.LAYER; // var bmpLayer:Bitmap = new Bitmap(Bitmap(layer.content).bitmapData); bmpLayer.smoothing = true; sprite.addChild(bmpLayer); // if (alphaLayer) { var bmpAlphaLayer:Bitmap = new Bitmap(Bitmap(alphaLayer.content).bitmapData); bmpAlphaLayer.blendMode = BlendMode.ALPHA; bmpAlphaLayer.smoothing = true; sprite.addChild(bmpAlphaLayer); } // container.addChild(sprite); }
另外,如果对Bitmap对象的bitmapData属性使用draw方法。
smoothing=true应该放在draw后面,否则绘画内容不会出现平滑。
不推荐对Bitmap对象的bitmapData属性使用draw,
因为很可能不小心draw了使用过addChild的显示对象。
相关推荐
Flex AS3 学习笔记总结 Flex 是 Adobe 开发的 RIA(Rich Internet Applications)工具,包括 Flex3 SDK、Flex Builder 和服务器产品,如 Lifestyle Data Services、CodeFushion。Flex 应用程序用 Flash.swf 文件...
AS3学习笔记FlashDevelop平台搭建配置 AS3学习笔记FlashDevelop平台搭建配置是关于如何搭建和配置FlashDevelop平台的学习笔记。下面是对该笔记中所涉及到的知识点的详细说明: 1. FlashDevelop平台简介 Flash...
这篇学习笔记概述了一些AS3的关键知识点,包括改变SWF属性、鼠标坐标、变量类型的检查、数据类型的传递方式、逻辑运算符的优化、Timer类的使用、访问控制修饰符以及异常处理。 1. **改变SWF属性**: AS3允许开发者...
而文件"〔分享〕AS3学习笔记 - RIACHINA 中国RIA开发者论坛 - Powered by Discuz!NT.htm"可能包含了社区论坛上关于AS3学习的经验分享、示例代码或疑难解答等内容,是深入学习AS3的好资源。对于初学者而言,理解AS3的...
根据提供的文件信息,我们可以整理出以下关于Flash AS3...以上是基于提供的学习笔记内容整理的关键知识点,这些知识点对于理解和掌握 AS3 的基本概念和编程技巧非常有帮助。希望对学习 Flash AS3 的初学者有所帮助。
AS3殿堂之路的学习笔记旨在帮助初学者理解AS3的基础概念,掌握核心语法,以便在开发富媒体内容和游戏时游刃有余。通过深入学习这些知识点,开发者可以构建功能丰富的交互式应用程序,并逐步进阶到更高级的编程实践。
3. **Spooled File操作**: - `WRKSPLF`:管理打印队列和输出,包括查看、打印和重定向Spooled文件。 4. **数据库操作**: - `CRTSAVF` 和 `SAVLIB`:创建保存文件并备份数据库。 - `RSTLIB`:从保存文件中恢复...
在"AS4AS学习笔记"中,我们可以期待找到关于如何利用AppleScript进行高效自动化操作的详细知识。 AppleScript是Apple公司设计的一种易于学习但功能强大的脚本语言,它的主要目标是让用户无需深入学习复杂的编程概念...
贝加莱AS学习笔记入门 贝加莱AS学习笔记入门是指贝加莱自动化解决方案的学习笔记,涵盖了贝加莱产品、POWERLINK、B&R PCC 软件平台等方面的知识点。本笔记旨在帮助学习者快速入门贝加莱AS,了解贝加莱产品的特点、...
AS400 自学笔记集锦 AS400学习笔记(V1.2) 自学使用的400操作命令集锦
AS400 基本学习笔记1 1. CL常用的命令:
### LabVIEW学习笔记知识点梳理 #### 一、调试技巧与数据监测 - **探针工具**: 在调试过程中,可以通过右键菜单中的`probe`和`custom probe`功能来设置探针,用于实时监测数据流。这有助于理解数据如何在各个节点...
3. 可编程唤醒模式:支持16位的可编程唤醒模式。 4. 支持加倍唤醒模式:可以通过特定的唤醒模式加倍来提高唤醒的准确性和可靠性。 5. 支持没有模式检测的唤醒:可以在没有任何模式检测的情况下进行唤醒。 6. 唤醒...
《AS3.0_AS3殿堂之路_笔记》是针对Adobe ActionScript 3.0(简称AS3)深入学习的一份详尽笔记,旨在帮助学习者系统掌握这一强大的编程语言,尤其对于想要在Flash平台上进行交互式内容开发的人员来说,这份笔记具有极...
云计算学习笔记 云计算是近年来非常热门的技术领域,它的出现改变了传统的计算模式,带来了许多便捷和优势。下面是关于云计算的学习笔记,涵盖了云计算的概念、演进过程、商业模式等方面的知识点。 云计算的概念 ...
AS400学习笔记整理 AS400是IBM开发的一种大型机系统,主要用于企业级应用系统的开发和部署。作为AS400初学者,学习AS400的命令和操作是非常重要的,本笔记整理了AS400学习笔记的主要内容,包括命令记录、示例解析、...
这份笔记详细记录了作者在学习过程中的理解和心得,旨在帮助其他学习者更好地掌握AS3的核心概念、语法特性和实际应用。 AS3是Adobe Flash Platform的主要编程语言,广泛应用于网页游戏开发、交互式多媒体内容以及富...
Papervision3D(PV3D)是一款强大的开源3D图形引擎,专为Adobe Flash平台设计,支持ActionScript 3.0(AS3),是Flash AS3中实现3D效果的重要工具。在本文中,我们将深入探讨PV3D的API文档、学习笔记以及全景案例,...
思科CCNA学习笔记 思科CCNA学习笔记是网络工程师的必备知识,涵盖了计算机网络的基本概念、OSI与TCP/IP协议框架、IP报文传输过程、传输层功能、TCP与UDP对比等内容。以下是该笔记的详细知识点: 一、OSI与TCP/IP...