Loader与URLLoader,SWFLoader

 

(1) Loader        
Loader 类可用于加载 SWF 文件或图像(JPG、PNG 或 GIF)文件。 使用 load() 方法来启动加载。 被加载的显示对象将做为 Loader 对象的子级添加。        
(2)URLLoader        
URLLoader 类以文本、二进制数据或 URL 编码变量的形式从 URL 下载数据。 在下载文本文件、XML 或其它用于动态数据驱动应用程序的信息时,它颇有用。URLLoader 对象会先从 URL 中下载全部数据,而后才将数据用于 ActionScript。 它会发出有关下载进度的通知,经过 bytesLoaded 和bytesTotal 属性以及已调度的事件,能够监视下载进度。在加载很是大的视频文件(如 FLV 的视频文件)时,可能会出现内存不足错误。
 
区别:一个用来加载可显示数据,一个用来加载非显示数据由于loader是继承与容器类的,因此首先它是个容器,而URLLoader 是继承与EventDispatcher,它不是容器URLLoader 类以文本、二进制数据或 URL 编码变量的形式从 URL 下载数据,在加载很是大的视频文件(如 FLV 的视频文件)时,可能会出现内存不足错误,返回的数据在data属性里面而loader多加载图片,swf等可视化对象,加载后做为惟一的子对象显示在列表上。

应用范围 
Loader: 多用于swf,图片(jpg,png,gif) 
URLLoader: 多用于文本文件(xml,php,jsp…)
使用方法 
[java]  view plain copy
 
  1. //Loader:  
  2. loader.contentLoaderInfo.addEventListener(Event.COMPLETE, loadComplete);   
  3. private function loadComplete(event:Event)  
  4. {   
  5.     trace("done");  
  6.     addChild(loader);  
  7. }  
  8.   
  9. //URLLoader:  
  10. xmlLoader.dataFormat=URLLoaderDataFormat.TEXT;   
  11. xmlLoader.addEventListener(Event.COMPLETE,xmlLoaded);   
  12. private function xmlLoaded(event:Event) {   
  13.     try {  
  14.         myXML = XML(event.target.data);area.text=myXML;  
  15.     }catch (e:TypeError)   
  16.     {  
  17.         area.text="Load faild:\n"+e.message;  
  18.     }   
  19. }  
Loader
在使用Loader来加载数据时,添加侦听事件时,注意必定要给Loader的 contentLoaderInfo属性增长事件,而不是给Loader对象增长事件。
[java]  view plain copy
 
  1. var loader:Loader = new Loader();  
  2. loader.contentLoaderInfo.addEventListener(Event.COMPLETE, completeHandler);  
  3. loader.contentLoaderInfo.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorHandler);  
  4. loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);  
 
(3)可使用SWFLoader和Loader两个类来加载子应用程序,多数状况下咱们使用SWFLoader。它是Loader的一个包装类,提供了不少附加功能,使加载子应用程序更简单。
SWFLoader有以下特征:
支持flex的样式和特效;而Loader类却不支持任何固有的样式和特效。
方便管理加载进度;若是使用Loader则首先要获取LoaderInfo引用。
 
是一个UIComponent组件。SWFLoader它本身管理了全部子显示对象,不须要添加多余的代码。
自动缩放显示内容的大小
 
能够加载Application之外的实现类,若是检测到不是一个Application,会自动进行处理。
能够处理不一样的版本。Loader不支持加载不一样的编译版本
 
当使用Loader加载不是受信任区域的swf时,必须提供一个遮罩来从新定位,不然它会显示在屏幕外面:
代码  
[java]  view plain copy
 
  1. import flash.display.*;    
  2. import flash.net.URLRequest;    
  3. var rect:Shape = new Shape();    
  4. rect.graphics.beginFill(0xFFFFFF);    
  5. rect.graphics.drawRect(0, 0, 100, 100);    
  6. addChild(rect);    
  7. var ldr:Loader = new Loader();    
  8. ldr.mask = rect;    
  9. var url:String = "http://www.unknown.example.com/content.swf";    
  10. var urlReq:URLRequest = new URLRequest(url);    
  11. ldr.load(urlReq);    
  12. addChild(ldr);   
SWFLoader加载外部swf是一个很好的方法,在进行Flex游戏开发的时候,咱们一般会须要不少Flash提供的游戏角色,这些角色能够每一个都是一个单独的swf,也能够是存在于一个swf文件中的各个元件。两种方法各有优劣:
1. 单独的swf,每一个角色独立性很强,能够在须要的时候才加载。将来修改角色也不会影响到其它角色。可是会有不少的swf须要管理。
2. 每一个角色是一个元件,存在于一个swf中,这种方法比较容易管理资源,比较干净。可是修改一个角色都须要从新编译swf,可能会误操做影响其它的元件。并且一次加载全部角色,可能会加载许多没必要要的元件,浪费带宽。


两种方法怎么选择,根据项目读者根据如下几个问题考虑:
1. 你的全部元件相互之间是否又不少公用元件?若是是的话,能够考虑放到一个swf中,由于这样会下降全部元件的文件量。
2. 你的全部元件是否都继承同一些类,实现同一些接口,调用同一些类?若是是的话,能够考虑放到一个swf中,这样比较容易管理类包,并且下降swf的文件量,由于共有的类只编译一次。
3. 你的全部元件是否彻底独立,没有任何关系?若是是的话,你能够考虑每一个角色独立的swf。
具体实现代码以下:
[java]  view plain copy
 
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"   
  3.                xmlns:s="library://ns.adobe.com/flex/spark"   
  4.                xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600"  
  5.                creationComplete="init()"  
  6.                >  
  7.     <fx:Declarations>  
  8.         <!-- Place non-visual elements (e.g., services, value objects) here -->  
  9.     </fx:Declarations>  
  10.     <fx:Script>  
  11.         <![CDATA[  
  12.             import mx.controls.SWFLoader;  
  13.             import mx.core.UIComponent;  
  14.    
  15.             private var swfLoader:SWFLoader = new SWFLoader();  
  16.             private function init():void{  
  17.                 swfLoader.addEventListener(Event.COMPLETE,swfLoadComplete);  
  18.                 swfLoader.load("assets/fishmomo.swf");  
  19.             }  
  20.             private function swfLoadComplete(e:Event):void{  
  21.                 /** 
  22.                  * 将整个swf都加载到flex舞台上 
  23.                  * 此方法将每一个flex要用的资源作成单独的swf,须要时才加载进来 
  24.                  */   
  25.                 addElement(swfLoader);  
  26.                 var swf:MovieClip = swfLoader.content as MovieClip;  
  27.                 //fish 是 swf主舞台上的一个鱼对象,属性命名为fish  
  28.                 //调用舞台上fish元件的say方法  
  29.                 swf.fish.say("Load a swf");  
  30.    
  31.                 /** 
  32.                  * 此方法能够把全部的flex要用的资源放到一个swf中 
  33.                  * 把须要在flex中使用的元件连接到一个类,并将此元件拖到flash舞台 
  34.                  * 经过类名,随意显示其中一个元件到flex舞台 
  35.                  */   
  36.                 var FishSymbol:Object = swfLoader.content.loaderInfo.applicationDomain.getDefinition("Fish");  
  37.                 var f:MovieClip = new FishSymbol() as MovieClip;  
  38.                 //调用元件的say方法  
  39.                 f.say("Load a symbol within a swf");  
  40.                 var ui:UIComponent = new UIComponent();  
  41.                 ui.addChild(f);  
  42.                 addElement(ui);  
  43.             }  
  44.         ]]>  
  45.     </fx:Script>  
  46. </s:Application>  

致使内存泄露的一些状况:

事件监听:
对父级对象加了监听函数,会形成内存泄露,例:
override protected function mouseDownHandler(…):void {
systemManager.addEventListener(“mouseUp”, mouseUpHandler);
……
}
解决:
在销毁对象的时候,remove掉这些监听,虽然弱引用也能够避免这些问题,但本身掌控感受更好。
但如下几种状况不会形成内存泄露:
弱引用:someObject.addEventListener(MouseClick.CLICK, handlerFunction, false, 0, true);
对本身的引用:this.addEventListener(MouseClick.CLICK, handlerFunction);
子对象的引用:
private var childObject:UIComponent = new UIComponent;
addChild(childObject);
childObject.addEventListener(MouseEvent.CLICK, clickHandler);
总之…有addEventListener,就removeEventListener一下吧,要为本身作的事负责~哈哈

清除引用
remove掉子对象后并不会删除该对象,他还保留在内存中,应该将引用设置为null
removeChildren(obj);
obj = null;

静态成员
Class (或MXML)中有:
public static var _eventService : MyService=new MyService();
解决:在dispose时,须要设置:
_eventService =null;

module (未解决)
moduleLoader unloadModule后
ModuleInfo 并不会被GC.
Garbage Collection in a MultiCore Modular Pipes Application
这篇文章介绍了一种GC策略,感受对于ModuleInfo 的GC无效。
(何尝试、未遇到)

CSS样式
module 中若是使用了shell的CSS定义或是<mx:Style> 这样的定义,那么这个module将不能GC.
弹出的窗口应该是一样的结果.
解决方法,使用动态CSS文件
module init中
StyleManager.loadStyleDeclarations(“css/myStyle.swf”);
module dispose中
StyleManager.unloadStyleDeclarations(“css/myStyle.swf”);

TextInput/Textarea(未解决)
若是module中有window使用了TextInput/Textarea控件,不点击没有问题,只要点上去,那么很遗憾了,module和所在窗体将不能被GC.
这个BUG很是严重,目前尚未解决方法。
memory leak when using TextInput and TextArea when click the keyboard 这里面附加的解决方法无效。
经过profiler分析,应该和Focusmanager有关,只有一点击就不会释放。

CursorManager.setCursor
使用了
cursorID = CursorManager.setCursor(iconClosed);
dispose时要
CursorManager.removeCursor(cursorID);

Bitmap
若是使用Bitmap,结束时须要调用其dispose方法,不然内存消耗巨大。
另外,BitmapData是能够共享使用的,多个Bitmap可使用同一BitmapData,节省很多内存。
var bmp:Bitmap =new Bitmap();
……..
if (bmp.bitmapData!=null) {
bmp.bitmapData.dispose();
}
Image
包含了Image对象时,在removeChildren时会形成不能释放(测试屡次,结果不一,建议仍是作以下处理)。
解决:
img.source = null;
this.removeChild(img);
img = null;

Loader、SWFLoader、声音、视频、Effect等…
若是是加载SWF文件,先中止播放。
中止声音的播放
中止正在播放的影片剪辑(Movieclip)
关闭任何链接的网络对象,例如Loader正在加载,要先close。
取消对摄像头或者麦克风的引用
取消事件监听器
中止任何正在运行的定时器,clearInterval()
中止任何Timer对象,timer.stop()
中止正在播放的效果(Effect)
其余

binding也疑似有memory leak 问题。
引用以及内存泄露相关博文和资料:
http://blogs.adobe.com/aharui/2007/03/garbage_collection_and_memory.html
http://www.craftymind.com/2008/04/09/kick-starting-the-garbage-collector-in-actionscript-3-with-air/
http://www.cnblogs.com/janyou/archive/2008/11/25/1340753.html
http://www.dreamingwell.com/articles/archives/2008/05/understanding_m.php
总结:因为以前Flash一直是在网页上使用,通常网页都是看完就关掉的,估计Adobe在内存回收这块也没有下太大的功夫,
如今AIR的出现使得内存管理也至关重要了,而且,AIR自己对内存的消耗就至关大,一个没有任何内容的初始建立的AIR程序,就得占掉10-20M+的内存…AIR还需改善.

Modules

为何要模块化;模块化提供了分离应用程序代码到不一样的swf文件上以便减小下载时间和文件大小。
使用Modules的好处是:
1. 主应用程序开始时不需立刻下载modules。应用程序会根据需求载入和卸载modules。
2. 因为每一个modules独立于其余应用程序modules,当须要改变一个modules时,你只须要重编译这个modules而不是整个应用程序。模块化可建立模块化应用程序是提升Flex框架性能的重要方面,提供更多能力控制下载时间和文件大小,使用modules,你能够根据哪些可被独立载入,哪些可被其余程序使用而分离应用程序代码。
 
优势是合理分割了主Application,模块化开发。更小的SWF文件体积,配合RSL和延迟加载策略,大大减小用户等待时间。
缺点就是容易引发内存泄露。

RSL

  RSL(Runtime Shared Library),即运行时加载库。当前L主要有3个级别的RSL,一个是Standard RSL(即一个网站内共享),一个是Cross-domain RSL(跨域共享),最后一个也是最关键的是Framework RSL(Flex框架共享)。
  功能说明
  Flex Builder在默认状况下,编译的每一个程序都是独立的。每一个程序都包含了所需类的一个副本,例如:在多个程序中都用到了VBox这个控件,那么每一个程序都要独立的拥有一个VBox类。由此形成了程序代码的重复,使得代码量增大不少。而RSL正是解决此问题的一种方法,它能够把共享代码提取出来,而后在相同域的程序之间进行共享。这些共享代码不会再编译进程序,而是放在单独的库中,供运行时加载。另外,RSL也能够在客户端进行缓存,所以不须要在每次使用程序时重复下载。
 
RSL(Runtime shared libraries)即动态连接库,在程序运行时由FlashPlayer动态加载。静态连接库是SWC文件,经过编译器的library-path和include-libraries
编译进应用程序。采用静态连接的应用程序SWF会产生比较大的文件以及更长的下载时间。使用RSL的应用程序载入时间短且文件比较小,并且提升了内存使用效率,只是
在开始须要花点时间下载RSL。RSL的强大致如今多个应用程序共享公共代码时,由于RSL只须要被下载一次,多个应用程序动态连接到相同的RSL,访问其中已经缓存在客
户端的资源。
使用RSL:
(1).在项目文件夹中点右建,选择"properties"-"Flex Build Path"-"Library Path"
(2).该选项卡上咱们看到"FrameWork linkage",默认是"Merged into cdoe"(FLEX4默认是RSL)
(3).点开下拉,选择"runtime shared library(RSL)"
(4).针对自定义的SWC,修改其link type为RSL,选择None,同时勾上Automatically extract swf to deployment path(自动将SWF提取到部署路径)。若是想对不一样域的RSL共享,则选择Digests(摘要),同时指定其Policy file url(策略文件)。具体可参考FLEX SDK中的SWC文件处理方式。
(5).点击OK

SWC

SWC 文件是相似 zip 的文件。静态连接库是SWC文件,经过编译器的library-path和include-libraries编译进应用程序。新建Flex Library Object或使用compc命令能够制做SWC。

E4X

E4X是在ECMA-357标准中定义的,并成为AS3的一部分。优势是提供更简明和可读性强的语法从XML中查找和提取数据。

profile工具

能够很方便地观察对象的建立和销毁,帮助检查内存泄露问题。

FlexUnit

FlexUnit - Flex单元测试框架 

其余

一、flex生成出来的文件都是很大,请问你用什么办法进行缩小呢?
(1)RSL
(2)Module
(3)外部加载资源

二、作一个flex项目,你认为成功的要素在哪呢?
(1)数据和需求等传统软件项目的成功要素
(2)模块化开发,MVC框架
(3)swf文件减肥,运行效率,内存泄露问题,前台优化
(4)开源组件的使用

三、flex 前端的性能优化
(1)、避免容器的多级嵌套,减小相对尺寸、相对定位的使用。
(2)、尽可能使用轻量级的容器
(3)、避免使用大致积的组件,好比DataGrid、AdvancedDataGrid
(4)、处理数据时多用分页的方式
(5)、少使用setStyle
(6)、使用延迟实例化加载子组件

4.Embed绑定图片有什么缺点?
答:直接编译到swf文件中,形成其体积过大。并且因为嵌入代码中,维护不便。

五、flex里调用JS措施?
答:直接在AS中利用ExternalInterface.call()来调用JS措施。如:
[java]  view plain copy
 
  1. import flash.external.ExternalInterface ;  
  2. ExternalInterface.call("JSFunction");  
  3. ExternalInterface.call("JSFunctionWithParameters","myParameter");  
  4. var result:String=ExternalInterface.call("JSFunctionWithReturn");  

六、用JavaScript调用ActionScript函数
答:利用ExternalInterface.addCallback在JavaScript里设置对Flex的回调措施而且在JavaScript里调用ActionScript措施。
[java]  view plain copy
 
  1. AS:  
  2. ExternalInterface.addCallback("function1",callback1);  
  3. privatefunctioncallback1():void  
  4. {  
  5. Alert.show("callback1executed");  
  6. }  
  7. JS:  
  8. container[swf].function1();  

六、FileReference
答:
[java]  view plain copy
 
  1. browse(typeFilter:Array = null):Boolean//揭示一个文件博览对话框,让用户抉择要上载的文件。  
  2. cancel():void//废止正在对该 FileReference 对象厉行的任何上载或下载垄断。  
  3. download(request:URLRequest, defaultFileName:String = null):void//敞开对话框,以批准用户从长途服务器下载文件.  
  4. upload(request:URLRequest, uploadDataFieldName:String = "Filedata", testUpload:Boolean = false):void//开始将用户抉择的文件上载到长途服务器。  

七、flash与flex是如何调停开发的?
答:这个问题可以这么来会意,万一是确乎必需用到FLEX SDK的利用,那咱们就可以发生一个flex工程,翔实必需flash作UI的时候,输出成swc做为flex的skin,万一说并没有需要flex sdk,只是为了编码得体而抉择flex的话,那咱们凡是发生一个as工程,让flex做为flash的编码器。

八、请说下事件里的currentTarget 和 target的区别?
答:在事件流的过程当中,目标阶段肯定的目标对象由Event中的target属性来记录,
冒泡阶段移动的游标则由currentTarget来记录。事件对象冒泡过程当中每往上移动一级,就会克隆出一个仅与前副本currentTarget不一样的新副本。

九、warning: unable to bind to property ” on class ‘Object’ (class is not an IEventDispatcher) 在使用ItemRender时,常常会出现这种警告?
答:ArrayCollection的子元素是没法做为数据源绑定的。能够声明中间变量,在override set data时将ArrayCollection的子元素传入,
而后再将中间变量做为新的绑定源便可。

十、经常使用的几个切换数据的组件好比: TabNavigator等都有属性 creationPolicy 你知道这种策略的使用方式是什么嘛?以及优,缺点呢?
答:延迟实例化。优势是能够更快地加载组件,缺点是首次访问其余组件时,因为须要从新加载此组件,可能会有必定的延迟。

十一、请试写一个自定义的验证组件
答:
[java]  view plain copy
 
  1. package myCompenent  
  2. {  
  3.     import mx.validators.Validator;//引用Validator类  
  4.     import mx.validators.ValidationResult;//引用ValidationResult类  
  5.     public class myValidators extends Validator  
  6.     {  
  7.         public function myValidators()//构造函数  
  8.         {  
  9.             super();  
  10.         }  
  11.         private var results:Array;//定义一个数组,用以存储错误  
  12.         //重写验证函数  
  13.         override protected function doValidation(value:Object):Array  
  14.         {  
  15.             var s:String = value as String;  
  16.             results = [];//清空数组  
  17.             results = super.doValidation(value);//先用继承类中的doValida tion方法验证  
  18.             if (results.length > 0)//若是验证时有错,返回错误信息  
  19.                 return results;  
  20.             if(s.length>6)//自定义验证,字符长度不超过6  
  21.             {  
  22.                 //记录出错信息  
  23.                 results.push(new ValidationResult(true,”text”,”StringTooLong”, “字符长度超过6了”));  
  24.             }  
  25.             return results;  
  26.         }  
  27.     }  
相关文章
相关标签/搜索