在上一章我们已经预告过本章的内容,有没有?我将在本章为大家带来如何发扬我们民族“勤俭节约”的美德的方法,我称之为“华丽终极超强死亡缓存策略”,小S present,here we go~!
缓存应用域
在上一章贫道已经提到过,最好把要用到的素材全部放到一个swf里面去,这样既可以压缩素材容量又可以减免在swf中使用时要加载多个素材,发起多个HTTP连接而增加的等待时间。那么在此章贫道将为列位施主展示一下具体的操作方式,让列位施主“理论联系实际”,做个爱学习的好孩子。
首先自然是打开Flash CS工具,然后把你需要用到的素材扔到库里面去然后设置它们的属性,让它们导出为ActionScript(不要忘了勾选'在第一帧中导出'单选框),下图是我做的一个简单的库,里面有常用的几种类型素材,图片,元件(可以是MovieClip、Sprite等多种类型):
<ignore_js_op>
之后进行测试影片后会生成一个swf,这个swf就是我们的素材集合了,把它(我这里命名为assets.swf)放到你的AS项目的某个目录中去(我这里放在assets目录下)。好了,准备工作妥当,接下来是上正菜得时候了。
我们需要在工程中设计一个单例来管理所有的素材,我叫它AssetsManager,它的原型如下:
- package com.zuisg.we
- {
- import flash.events.EventDispatcher;
- public class AssetsManager extends EventDispatcher
- {
- private static var _instance:AssetsManager = null;
- //构造函数接收一个SingletonClass类型的参数,而SingletonClass类只有AssetsManager能访问它,
- //所以在外部无法实例化一个AssetsManager
- public function AssetsManager( singleton:SingletonClass ){}
- /**
- * 得到全局唯一的AssetsManager类实例
- */
- public static function get instance():AssetsManager
- {
- if( _instance == null )_instance = new AssetsManager( new SingletonClass() );
- return _instance;
- }
- }
- }
- class SingletonClass{}//包外类,只有此文件内的类可以访问之,也就是说只有AssetsManager能访问它
这是一个标准的单例类,它继承了EventDispatcher所以它具备了发送事件的能力,为什么要让它具备发送事件的能力呢?因为加载素材需要时间,外面不能立即拿到AssetsManager提供的素材,所以就需要侦听一个“加载完成”事件来知道何时才能开始去问AssetsManager要素材。
因为本节的话题是“缓存应用域”,所以我们需要给AssetsManager增加一个ApplicationDomain类型的属性来保存被加载的swf的应用域。ApplicationDomain(应用域)是什么东西呢?它是分散的类定义组的一个容器,所有ActionScript类的定义语句都会被保存于应用域中,就如刚才我们在fla文件库中的那几个素材被导出为ActionScript并分别被命名为了myImage, myMovie, myFuckingMovie,这些定义都会在被编译成为swf之后保存于此swf的应用域中。之后我们设计一个共有方法来允许外部控制加载的开始,并在加载完毕后保存被加载swf文件的应用域:
- private var appDomain:ApplicationDomain;
- ………………
- /**
- * 加载一个swf并保存应用域
- * @param url 欲加载swf路径
- *
- */
- public function loadResource( url:String ):void
- {
- var loader:Loader = new Loader();
- loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete);
- loader.load( new URLRequest( url ) );
- }
- private function onComplete( e:Event ):void
- {
- //被加载对象的应用域一般保存于LoadInfo中
- appDomain = (e.currentTarget as LoaderInfo).applicationDomain;
- dispatchEvent( new AssetsEvent(AssetsEvent.LOAD_COMPLETE_E) );
- }
这里我们抛出的是一个自定义的事件叫做AssetsEvent,它的代码如下:
- package com.zuisg.we.events
- {
- import flash.events.Event;
- public class AssetsEvent extends Event
- {
- /** 素材加载完毕后将会发送此事件*/
- public static const LOAD_COMPLETE_E:String = "load complete event";
- public function AssetsEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false)
- {
- super(type, bubbles, cancelable);
- }
- }
- }
当外部调用loadResource方法并传入一个加载路径后就可以开始加载,并在监听到LOAD_COMPLETE_E事件后得知此时可以开始问AssetsManager要素材资源了。此时我们已经保存了被加载对象的应用域,那么要得到应用域中保存的类定义可以使用ApplicationDomain的getDefinition方法。下面的代码是我设计的一个供外部调用的根据类名来获取素材实例的一个方法:
- /**
- * 根据类名获取素材实例
- * @param className 类名
- * @return 资源实例
- *
- */
- public function getAssetByClass( className:String ):Object
- {
- var result:Object;
- try
- {
- var classReference:Class = appDomain.getDefinition( className ) as Class;
- result = new classReference();
- }
- catch( e:Error )
- {
- trace("不存在此类定义");
- }
- return result;
- }
有了如此卡哇伊如此好用的一个方法之后外部就可以根据需要来取资源实例了:
- package
- {
- import com.zuisg.we.AssetsManager;
- import flash.display.Bitmap;
- import flash.display.BitmapData;
- import flash.display.MovieClip;
- import flash.display.Sprite;
- import flash.events.Event;
- public class OptimizeYourFlashApp extends Sprite
- {
- public function OptimizeYourFlashApp()
- {
- AssetsManager.instance.addEventListener( AssetsEvent.LOAD_COMPLETE_E, onLoadComplete );
- AssetsManager.instance.loadResource( "assets/assets.swf" );
- }
- private function onLoadComplete( e:AssetsEvent):void
- {
- var mc:MovieClip = AssetsManager.instance.getAssetByClass( "myMovie" ) as MovieClip;
- if( mc != null )
- {
- addChild( mc );
- }
- var bmd:BitmapData = AssetsManager.instance.getAssetByClass( "myImage" ) as BitmapData;
- if( bmd != null )
- {
- var bmp1:Bitmap = new Bitmap( bmd );
- var bmp2:Bitmap = new Bitmap( bmd );
- addChild( bmp1 );
- addChild( bmp2 );
- bmp2.x = bmp1.width;
- }
- }
- }
- }
由于AssetsManager是一个单例类,所以在工程中的任何地方都能够调用AssetsManager.instance.getAssetByClass来获取想要的资源,但是必须确保资源已经加载完毕。如上就是缓存应用域的方法,只需加载一次资源文件即可满足整个项目的资源使用。
缓存已加载资源
如果你在项目开发中无法做到把全部资源打包成一个swf,那么你不得不面对一个严峻的事实那就是多次甚至大量的加载。那么现在由贫道提供的“华丽终极超强死亡缓存策略”可能会对你有所帮助。此策略只适合缓存位图数据(bitmapData),为什么呢?因为我们知道,像MovieClip、Sprite、Bitmap这些常用的显示对象是没办法重用和复制的。举个例子,看下面的代码:
- var mc1:MovieClip = resource;//resource是一个可用的MovieClip资源实例
- var mc2:MovieClip = resource;
- addChild( mc1 );
- addChild( mc2 );
- mc2.x = 200;
如果运行这段代码那么我们只可能看到位于200位置的mc2的外形,看不见mc1的外形,因为把一个MovieClip实例赋值给一个对象是“地址引用”而非“值引用”,对于Sprite、Bitmap、Loader这些东西来说也是一样的。
不过还好,有一个幸存者:BitmapData是可用复用的,如果把一个BitmapData实例赋值给两个Bitmap实例的bitmapData属性(或者你可以调用BitmapData的clone方法来实现拷贝),那么这两个Bitmap都会显示出来。所以贫道的“华丽终极超强死亡缓存策略”的实质就是缓存BitmapData。
那么为了体现出贫道“华丽终极超强死亡缓存策略”的威力,还是先看看使用一般加载的方法会耗时多少吧,还是在我们刚才创建的AssetsManager基础上增加功能,写一个方法来读取图片:
- public function loadImage( url:String ):void
- {
- var loader:Loader = new Loader();
- loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onImageComplete);
- loader.load( new URLRequest( url ) );
- }
- private function onImageComplete( e:Event ):void
- {
- try
- {
- var loadInfo:LoaderInfo = e.currentTarget as LoaderInfo;
- //取出被加载图片的位图数据
- var bmd:BitmapData = (loadInfo.content as Bitmap).bitmapData;
- //发送加载完成事件
- var event:AssetsEvent = new AssetsEvent(AssetsEvent.LOAD_COMPLETE_E, AssetsEvent.CACHE_POLICY_BITMAPDATA);
- event.loadedBitmapData = bmd;
- dispatchEvent( event );
- }
- catch( e:Error )
- {
- trace("加载对象格式错误!");
- }
- }
很容易理解吧?这段代码列位应该已经用的应该很多了。哦,忘了说了,我把AssetsEvent又改装了一下,为它增加了两个属性:
- package com.zuisg.we.events
- {
- import flash.display.BitmapData;
- import flash.events.Event;
- public class AssetsEvent extends Event
- {
- /** 素材加载完毕后将会发送此事件*/
- public static const LOAD_COMPLETE_E:String = "load complete event";
- /**
- * 缓存策略:缓存应用域
- */
- public static const CACHE_POLICY_APPDOMAIN:String = "cache application domain";
- /**
- * 缓存策略:缓存位图数据
- */
- public static const CACHE_POLICY_BITMAPDATA:String = "cache bitmapData";
- /** 被加载位图数据 */
- public var loadedBitmapData:BitmapData;
- /** 加载策略 */
- public var cachePolicy:String;
- public function AssetsEvent(type:String, cachePolicy:String, bubbles:Boolean=false, cancelable:Boolean=false)
- {
- super(type, bubbles, cancelable);
- this.cachePolicy = cachePolicy;
- }
- }
- }
当我使用AssetsManager中的加载方法加载完成后会派发一个AssetsEvent 事件,在外部侦听到此事件后我们可以根据此事件的cachePolicy属性判断我们当初加载的是swf并缓存了它的应用域还是加载的是图片并缓存了它的bitmapData。如果是后者,那么我们就可以取出事件中携带的被加载图片的bitmapData来为我所用(保存于loadedBitmapData这个属性里面)。
那么现在在外部调用一下这个新方法并记录两次加载同一张图片的耗时情况:
- public class OptimizeYourFlashApp extends Sprite
- {
- private var startTime:int;
- private var i:int = 0;
- public function OptimizeYourFlashApp()
- {
- AssetsManager.instance.addEventListener( AssetsEvent.LOAD_COMPLETE_E, onLoadComplete );
- startTime = getTimer();
- AssetsManager.instance.loadImage( "assets/27.jpg" );
- }
- private function onLoadComplete( e:AssetsEvent ):void
- {
- if( e.cachePolicy == AssetsEvent.CACHE_POLICY_BITMAPDATA && e.loadedBitmapData != null )
- {
- var bmp:Bitmap = new Bitmap( e.loadedBitmapData );
- i++;
- trace("第" + i + "次耗时:" + (getTimer() - startTime) + "毫秒");
- if( i < 2 )
- {
- startTime = getTimer();
- AssetsManager.instance.loadImage( "assets/27.jpg" );
- }
- }
- }
- }
测试结果如下:
第1次耗时:138毫秒
第2次耗时:38毫秒
从这个结果可以看出flash player自身就具备了一定量的缓存功能,不过和贫道的“华丽终极超强死亡缓存策略”比起来还是差得远了。
首先为列位介绍一个类:Dictionary。它是一个动态类,我们可以用它来创建属性的动态集合。举个例子:
- var dic:Dictionary = new Dictionary()
- var name:String = "shit";
- dic[name] = new Object()
这样我们就把一个对象以name为键值存入了一个Dictionary当中,取数据时只要访问dic[name]即可。当一个Dictionary中存有多个对象是我们就可以用键值来进行访问某个对象。
接下来在AssetsManager中设置一个Dictionary的对象来存放已加载过的BitmapData:
- /**
- * BitmapData缓存字典
- */
- private var _cacheOfImage:Dictionary = new Dictionary(true);
这里在Dictionary的构造函数中设置第一个参数为true可以开启弱引用,帮助手册上的解释是:如果对某个对象的唯一引用位于指定的 Dictionary 对象中,则键符合垃圾回收的条件,并且在回收对象时会被从表中删除。 这也是使用Dictionary的好处之一。当然,你也可以用Array数组来实现ary[name] = obj这样的键-值存储,但是只是为了进行键-值存储的话还是推荐使用轻量级且具备弱引用功能的Dictionary。
之后直接先给出改进后的loadImage方法:
- /**
- * 加载图片并缓存
- * @param url 加载图片路径
- *
- */
- public function loadImage( url:String ):void
- {
- //若缓存中存在此资源则直接拿出来使用
- if( _cacheOfImage[url] != null )
- {
- var e:AssetsEvent = new AssetsEvent(AssetsEvent.LOAD_COMPLETE_E, AssetsEvent.CACHE_POLICY_BITMAPDATA);
- e.loadedBitmapData = ( _cacheOfImage[url] as BitmapData ).clone();
- dispatchEvent( e );
- }
- //若缓存中不存在此资源则进行加载
- else
- {
- var loader:Loader = new Loader();
- //将url暂存于Loader的name属性中
- loader.name = url;
- loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onImageComplete);
- loader.load( new URLRequest( url ) );
- }
- }
- private function onImageComplete( e:Event ):void
- {
- try
- {
- var loadInfo:LoaderInfo = e.currentTarget as LoaderInfo;
- //取出保存于Loader中的加载路径名
- var name:String = loadInfo.loader.name;
- //取出被加载图片的位图数据
- var bmd:BitmapData = (loadInfo.content as Bitmap).bitmapData;
- //根据路径名缓存位图数据
- _cacheOfImage[ name ] = bmd;
- //发送加载完成事件
- var event:AssetsEvent = new AssetsEvent(AssetsEvent.LOAD_COMPLETE_E, AssetsEvent.CACHE_POLICY_BITMAPDATA);
- event.loadedBitmapData = bmd;
- dispatchEvent( event );
- //记得移除无用的事件侦听,让无用对象能被垃圾回收
- loadInfo.removeEventListener(Event.COMPLETE, onImageComplete);
- }
- catch( e:Error )
- {
- trace("加载对象格式错误!");
- }
- }
上面的代码是我精心设计过的加载方法,提供多进程并行开始下载,因为每一个对象调用loadImage方法时都会新new一个Loader,这样产生的1对1关系能确保在一次收到多个下载请求时能够正确地实现并行加载,我们把一些加载完成后要用到的信息放在Loader的name属性里(我很喜欢用这个闲置的属性^_^),待加载完成后将加载图片的bitmapData以它的文件路径名进行保存。那么在第二次加载同一个路径名的图片时就可以直接从缓存的Dictionary对象中取出来直接用了。
最后来看看使用新的loadImage方法进行加载的速度测试结果,文档类里面不需要改代码,直接调试,输出结果如下:
第1次耗时:208毫秒
第2次耗时:0毫秒
虽然是意料之中但也没想到会那么快,第二次加载居然实现了零等待时间!
不过在使用过程中你也许会碰到一个问题:我在A类和B类中同时写了如下代码:
- AssetsManager.instance.addEventListener( AssetsEvent.LOAD_COMPLETE_E, onLoadComplete );
- AssetsManager.instance.loadImage( "assets/xx.jpg" );
这两个类都需要使用AssetsManager的loadImage方法进行图片加载,所以都对AssetsManager的单例进行了完成事件的侦听。假设A加载图片得速度比B快,那么A先加载完毕后在AssetsManager中会抛出一个完成事件,事件中将会携带A所加载图片的位图数据,但是由于AssetsManager是个单例,而在A类和B类中又同时对AssetsManager进行了事件侦听,所以在A侦听到加载完成事件的同时B也会侦听到了,这将会导致数据紊乱。
<ignore_js_op>
解决方案是为每一个加载请求者添加一个id,然后把这个id放入加载完成事件中去,当加载完毕一个图片后派发LOAD_COMPLETE_E事件,全部侦听此事件的类都会侦听到,侦听到事件后去查看此事件中的id,如果跟自己的一样那就进行下一步操作,如果不是则掠过。这就好比是领快递,是我的包裹我就领走,不是就忽略。
好了,接下来开始把想法付诸代码吧。先为AssetEvent增加一个id属性,之后修改AssetsManager中的loadImage代码:
- /**
- * 加载图片并缓存
- * @param url 加载图片路径
- * @param id 加载请求者的标识符
- */
- public function loadImage( url:String, id:String ):void
- {
- //若缓存中存在此资源则直接拿出来使用
- if( _cacheOfImage[url] != null )
- {
- var e:AssetsEvent = new AssetsEvent(AssetsEvent.LOAD_COMPLETE_E, AssetsEvent.CACHE_POLICY_BITMAPDATA);
- e.loadedBitmapData = ( _cacheOfImage[url] as BitmapData ).clone();
- e.id = id;//赋予事件id
- dispatchEvent( e );
- }
- //若缓存中不存在此资源则进行加载
- else
- {
- var loader:Loader = new Loader();
- //将url以及id暂存于Loader的name属性中,以下划线分隔各个信息
- loader.name = url + "_" + id;
- loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onImageComplete);
- loader.load( new URLRequest( url ) );
- }
- }
- private function onImageComplete( e:Event ):void
- {
- try
- {
- var loadInfo:LoaderInfo = e.currentTarget as LoaderInfo;
- //取出保存于Loader的name属性中的信息
- var info:Array = loadInfo.loader.name.split('_');
- var name:String = info[0];//下划线前的字符串是加载路径
- var id:String = info[1];//下划线后的字符串是id
- //取出被加载图片的位图数据
- var bmd:BitmapData = (loadInfo.content as Bitmap).bitmapData;
- //根据路径名缓存位图数据
- _cacheOfImage[ name ] = bmd;
- //发送加载完成事件
- var event:AssetsEvent = new AssetsEvent(AssetsEvent.LOAD_COMPLETE_E, AssetsEvent.CACHE_POLICY_BITMAPDATA);
- event.loadedBitmapData = bmd;
- event.id = id;
- dispatchEvent( event );
- //记得移除无用的事件侦听,让无用对象能被垃圾回收
- loadInfo.removeEventListener(Event.COMPLETE, onImageComplete);
- }
- catch( e:Error )
- {
- trace("加载对象格式错误!");
- }
- }
之后,我们在外部使用时需要在调用loadImage方法时传入第二个参数id,并完成事件的侦听函数中判断事件中的id是否和自己的匹配:
- private var id:String;
- public function OptimizeYourFlashApp()
- {
- AssetsManager.instance.addEventListener( AssetsEvent.LOAD_COMPLETE_E, onLoadComplete );
- id = Math.random().toString();//随机生成一个标识符
- AssetsManager.instance.loadImage( "assets/27.jpg", id );
- }
- private function onLoadComplete( e:AssetsEvent ):void
- {
- if( e.cachePolicy == AssetsEvent.CACHE_POLICY_BITMAPDATA && e.loadedBitmapData != null
- && e.id == id )
- { //do something }
- }
首先为AssetEvent增加一个事件类型的常量,一个被加载影片转换而成的bitmapData数组属性:
- public class AssetsEvent extends Event
- {
- …………
- /**
- * 缓存策略:缓存动画数据
- */
- public static const CACHE_POLICY_MOVIE:String = "cache movie";
- /** 被加载影片剪辑的bitmapData数组 */
- public var loadedMovie:Array;
- ……
- }
- /**
- * 加载影片剪辑并转化为BitmapData数组
- * @param url 加载路径
- * @param id 加载请求者id
- * @param symbol 加载影片剪辑中的元件名,若为空,则显示整一个舞台
- *
- */
- public function loadMovie( url:String, id:String, symbol:String="" ):void
- {
- //若缓存中存在此资源则直接拿出来使用
- if( _cacheOfImage[url] != null )
- {
- var e:AssetsEvent = new AssetsEvent(AssetsEvent.LOAD_COMPLETE_E, AssetsEvent.CACHE_POLICY_MOVIE);
- e.loadedMovie = ( _cacheOfImage[url] as Array ).concat();//拷贝一份bitmapData数组
- e.id = id;
- dispatchEvent( e );
- }
- //若缓存中不存在此资源则进行加载
- else
- {
- var loader:Loader = new Loader();
- //所有信息均暂存于Loader的name属性中,以下划线分隔各个信息
- loader.name = url + "_" + id + "_" + symbol;
- loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onMovieComplete);
- loader.load( new URLRequest( url ) );
- }
- }
- private function onMovieComplete( e:Event ):void
- {
- try
- {
- var loadInfo:LoaderInfo = e.currentTarget as LoaderInfo;
- //取出保存于Loader的name属性中的信息
- var info:Array = loadInfo.loader.name.split('_');
- var name:String = info[0];//加载路径
- var id:String = info[1];//id
- var symbol:String = info[2];//动画元件名
- //取出被加载的影片剪辑
- var mc:MovieClip;
- var bmds:Array;
- if( symbol != null )
- {
- var classReference:Class = loadInfo.applicationDomain.getDefinition( symbol ) as Class;
- mc = new classReference() as MovieClip;
- }
- else
- {
- mc = loadInfo.content as MovieClip;
- }
- //取出正确的影片剪辑对象后转化为bitmapData数组
- if( mc != null )bmds = M2B.transformM2B( mc, mc.width, mc.height );
- //根据路径名缓存位图数据
- _cacheOfImage[ name ] = bmds;
- //发送加载完成事件
- var event:AssetsEvent = new AssetsEvent(AssetsEvent.LOAD_COMPLETE_E, AssetsEvent.CACHE_POLICY_MOVIE);
- event.loadedMovie = bmds;
- event.id = id;
- dispatchEvent( event );
- //记得移除无用的事件侦听,让无用对象能被垃圾回收
- loadInfo.removeEventListener(Event.COMPLETE, onImageComplete);
- }
- catch( e:Error )
- {
- trace("加载对象格式错误!");
- }
- }
- package
- {
- import com.zuisg.we.AnimationObject;
- import com.zuisg.we.AssetsManager;
- import com.zuisg.we.events.AssetsEvent;
- import flash.display.Sprite;
- import flash.utils.getTimer;
- public class OptimizeYourFlashApp extends Sprite
- {
- private var startTime:int;
- private var i:int = 0;
- private var id:String;
- public function OptimizeYourFlashApp()
- {
- AssetsManager.instance.addEventListener( AssetsEvent.LOAD_COMPLETE_E, onLoadComplete );
- id = Math.random().toString();//随机生成一个标识符
- startTime = getTimer();
- AssetsManager.instance.loadMovie( "assets/assets.swf", id, 'myMovie' );
- }
- private function onLoadComplete( e:AssetsEvent ):void
- {
- if( e.cachePolicy == AssetsEvent.CACHE_POLICY_MOVIE && e.loadedMovie != null
- && e.id == id )
- {
- var animationObj:AnimationObject = new AnimationObject();
- animationObj.imgList = e.loadedMovie;
- animationObj.play();
- animationObj.x = i * 200;
- animationObj.y = 100;
- addChild( animationObj );
- i++;
- trace("第" + i + "次耗时:" + (getTimer() - startTime) + "毫秒");
- if( i < 2 )
- {
- startTime = getTimer();
- AssetsManager.instance.loadMovie( "assets/assets.swf", id, 'myMovie' );
- }
- }
- }
- }
- }
好好阅读并理解我奉献给列位的这个AssetsManager吧,这里给出源码供列位道友使用,enjoy it~! <ignore_js_op>AssetsManager.rar (4.45 KB, 下载次数: 220)
最近有道友提出了一个问题就是在之前讲的缓存应用域的代码只能适用于存在单一素材文件的情况下。如果我当前falsh应用所使用的素材全部存在一个resource.swf文件中的话上面的代码是不会存在什么问题的,但是若当前falsh应用所使用的素材存放于多个swf文件下的话就会出现问题了,注意到以下代码:
- private function onComplete( e:Event ):void
- {
- //被加载对象的应用域一般保存于LoadInfo中
- appDomain = (e.currentTarget as LoaderInfo).applicationDomain;
- dispatchEvent( new AssetsEvent(AssetsEvent.LOAD_COMPLETE_E) );
- }
那么这里说一下解决的方案。在Flash AS3中,我们一般在使用Loader对象加载文件时往往会忽略掉其load方法的第二个参数,我们一起来看看AS3语言参考手册中对load方法第二个参数的解释:
- context:LoaderContext (default = null) — LoaderContext 对象,它具有定义下列内容的属性:
- Flash Player 是否应在加载对象时检查策略文件是否存在
- 被加载的对象的 ApplicationDomain
- 加载的对象的 SecurityDomain
- /**
- * 带缓存功能的素材管理类
- * @author S_eVent
- *
- */
- public class AssetsManager extends EventDispatcher
- {
- /** 当前应用的应用域副本 */
- private var appDomain:ApplicationDomain = new ApplicationDomain(ApplicationDomain.currentDomain);
- ……
- /**
- * 加载一个swf并保存应用域
- * @param url 欲加载swf路径
- *
- */
- public function loadResource( url:String ):void
- {
- var loader:Loader = new Loader();
- loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete);
- var loaderContext:LoaderContext = new LoaderContext(false, appDomain);//将被加载的swf文件应用域合并至appDomain中
- loader.load( new URLRequest( url ), loaderContext );
- }
- ……
- private function onComplete( e:Event ):void
- {
- dispatchEvent( new AssetsEvent(AssetsEvent.LOAD_COMPLETE_E, AssetsEvent.CACHE_POLICY_APPDOMAIN) );
- }
- }
- public class Test extends Sprite
- {
- public static const ASSETS_FLODER_PATH:String = "assets/";
- private var resourceList:Array = ["PlayResource.swf", "resource.swf"];
- private var currentLoadingIndex:int = 0;
- public function Test()
- {
- currentLoadingIndex = 0;
- loadResource( resourceList[currentLoadingIndex] );
- }
- private function loadResource( url:String ):void
- {
- AssetsManager.instance.addEventListener( AssetsEvent.LOAD_COMPLETE_E, onLoadComp );
- AssetsManager.instance.loadResource( ASSETS_FLODER_PATH + url );
- }
- private function onLoadComp( e:AssetsEvent ):void
- {
- if( ++currentLoadingIndex < resourceList.length )
- {
- loadResource( resourceList[currentLoadingIndex] );
- }
- //全部素材已经加载完毕
- else
- {
- //添加来自PlayResource.swf中的元件
- var child1:MovieClip = AssetsManager.instance.getAssetByClass("exclamation") as MovieClip;
- if( child1 )
- {
- child1.x = child1.y = 50;
- addChild(child1);
- }
- //添加来自resource.swf中的元件
- var child2:Sprite = AssetsManager.instance.getAssetByClass("GEM_COLLECT_FLOWER") as Sprite;
- if( child2 )
- {
- child2.x = 200;
- child2.y = 50;
- addChild(child2);
- }
- }
- }
- }