使用Loader载入和组织资源分布

对于一个大型应用程序,资源和代码不可能全部包含在一个 swf 文件中。资源应该分布到不同的位置,就像组建网站一样。网站是依靠网页组建成整个网站的框架,每个网页通过标签载入外部文件。在页面中标签可以载入外部内容,也可以通过标签把部分内容写在网页中,例如 js 代码和 xml 文件。 as3 应用程序的组织与网站管理类似,支撑网站架构的是 swf 文件,实现载入的不是标签,而是 Loader 加载器。

虽然 b/s 结构的 as3 应用程序也以网页形式出现,但是网页只起到辅助作用,网页使用 activeX 控件播放 swf 文件,相当于 flash 播放器。组织整个 as3 应用程序的类主要有 Loader 类、 LoaderInfo 类、 LoaderContex 类、 ApplicationDomain SecurityDomain 类,其中最核心的类是 Loader 类。

Loader 类的特点

Loader 只能载入外部图片和 swf ,在格式上有局限性,但 Loader 提供从内存中加载图片和 swf 的方法,可以配合 URLLoader 进行扩展,从而对外部资源进行加密或分割。 Loader 侧重点不在于加载的数据类型,而在于组织应用程序资源分布。当加载图片时, Loader 是一个纯粹的资源加载器;但当加载包括代码的 swf 时, Loader 变成了应用程之间的连接器,是 swf 文件之间的纽带,由于 swf 中又可以使用 Loader 载入 swf Loader 成为树状资源分布结构中的节点。 Loader 承载如此重要功能,为此 as3 Loader 进行了精心的设计:

1.   轻量级

Loader 直接继承于 DisplayObjectContainer ,增加的成员只有 7 个,保证在复杂的应用程序中不会因为大量的 Loader 导致体积迅速膨胀。

2.   功能单一

由于设计目的明确,虽然是容器,但只能放入一个显示子对象,再次表明只用于加载,不做普通容器使用,尝试增删子对象的代码会引发错误。

3.   运行稳定。

即使加载复杂的 swf 也能保证正常运行。每个 swf root 属性引用自身的文档类对象,避免载入后导致路径错误。

4.   加载机制成熟。

Loader 使用 LoaderInfo 作为加载信息对象,加载信息被加载器和加载内容共享,可控制性强。 Loader 使用安全域和应用程序域对加载代码进行管理,满足不同的需求。

加载过程

一个正常的资源加载过程如下:

资源加载过程与数据加载过程很相似,但最大的区别是在信息对象的事件中处理数据而不是在加载器事件中处理数据,这是初学者最容易犯错地方。所有的加载事件都定义在 LoadrInfo 对象中, Loader 本身没有定义加载事件,这是需求所致,因为 LoaderInfo 对象被加载器和被加载的内容共享,两方面都要了解加载状态和加载信息。对于加载器, LoaderInfo 对象是 Loader contentLoaderInfo 属性,对于被加载的 swf 而言, LoaderInfo 是文档类的 loaderInfo 属性,如下图:

LoaderInfo.png

loaderInfo 属性是显示对象的属性,所有显示对象的 loaderInfo 都指向文档类的 LoaderInfo 对象,就像 stage 属性一样。 Loader 也是显示对象,因此也有 loaderInfo 属性,为了区分自身的加载信息和加载内容的加载信息, Loader 把加载内容的加载信息定义为 contentLoaderInfo 属性,自身 loaderInfo 属性仍然指向文档类的 loaderInfo

LoaderInfo 对象记录的信息

对于加载器的 contentLoaderInfo 属性默认虽然不为空,但却是个临时对象,在加载过程中会慢慢收集信息更新这个对象,等到加载完毕后共享信息才完整。所以在加载过程中,你只能访问共享信息中的加载进度,网络状态等信息,不能访问加载内容的完成信息。

对于文档类的 LoaderInfo 属性,当 swf 文件被创建时就记录了 swf 的信息,这个 swf 被加载后这些信息会和加载器一同共享。 LoaderInfo 中包含的信息丰富,它不仅记录 swf 的创建信息,还反应运行环境,加载内容的安全域和应用程序域。

包含引用

content:DislayObject

加载内容的引用,与 Loader content 属性相同。

 

loader:Loader

加载器的引用。

加载内容信息

contentType:String

加载类型,如下表:

类型

说明

"application/x-shockwave-flash"

swf 文件

"image/jpeg"

jpg 文件

"image/gif"

gif 文件

"image/png"

png 文件

 

bytesLoaded:uint

已加载字节数。

 

bytesTotal:uint

总字节数。开始为 0 ,触发 prgrass 事件后可访问。

 

width:int

加载内容的宽度。

 

height:int

加载内容的高度。

 

frameRate:Number

加载 swf 帧速。

 

url:String

加载内容的网址,忽略参数。

 

bytes:ByteArray

加载内容的二进制数据。通过这个属性可以把加载内容进行复制。

 

actionScriptVersion : uint

加载内容的 as 版本。

 

swfVersion : uint

发布 swf 的版本

 

文档类 swf 信息

loaderURL:String

加载器所在文档类地址,忽略参数。

 

parameters:Object

来自页面设置的变量。

 

安全访问

childAllowsParent:Boolean

子集是否可以被父级访问。

 

parentAllowsChild:Boolean

父级是否可以被子集访问。

 

应用程序域

applicationDomain:ApplicationDomain

通过 loaderContext 参数指定载入的应用程序域。

 

sameDomain:Boolean

子集和父级是否在相同的安全域中。

跨边界事件

sharedEvents:EventDispatcher

共享的 EventDispatcher 对象, EventDispatcher 不属于任何一方,用于跨边界交换事件,即使双方互不信任也可以访问 EventDispatcher 属性。 sharedEvents 主要用于在不同安全域的 swf 交换数据。

两种加载方法

可以使用两种方式加载资源:

1.   从外部加载

使用 load(request:URLRequest, context:LoaderContext = null):void 方法加载外部文件,例如:

var loader:Loader = new Loader();

loader.contentLoaderInfo.addEventListener(Event.INIT, initHandler);

var request:URLRequest = new URLRequest("http://www.flash.com.example.jpg");

loader.load(request);

addChild(loader);

 

function initHandler(event:Event):void

{

    trace(loader.contentLoaderInfo);

}

 

2.   从内存中加载

使用 loadBytes(bytes:ByteArray, context:LoaderContext = null):void 从内存中加载,二进制必须是 Loader 可以识别的数据类型。例如:

var urlRequest:URLRequest=new URLRequest("content.swf");

var urlLoader:URLLoader=new URLLoader();

urlLoader.addEventListener(Event.COMPLETE,loadSwf);

urlLoader.dataFormat=URLLoaderDataFormat.BINARY;

var loader:Loader=new Loader();

var ba:ByteArray;

 

function loadSwf(event:Event):void

{

   ba=urlLoader.data;

   loader.loadBytes(ba);

   addChild(loader);

}

urlLoader.load(urlRequest);

 

当需要对载入的资源加密时,把加密的资源载使用 URLRequest URLStream Socket 载入后进行解密,然后通过 Loader 从内存中加载。当需要进行资源分割时,把需要的资源打包到一个压缩文件中以二进制形式载入后解密,根据每个文件的大小和顺序进行分离。然后使用 Loader 从内存中分别载入。

加载路径

加载过程中可能会在加载路径上犯错:

顶级路径问题:

一个 swf 能加载同级下的文件,但是把这个 swf 载入到另外一个不同目录的 swf 中加载文件就会找不到路径,那是因为新的路径是相对于顶级文档类的。

网页中的 swf

如果把一个包含加载器的 swf 放置在网页中,而网页和 swf 不在一个目录下会导致路径错误,因为所有加载路径都相对于包含 swf 的网页。

监视加载进度

通过 LoaderInfo 对象加载器和被加载的 swf 都可以监视加载进度,两方都可以制作加载进度条。在被加载的 swf 中制作进度条时,由于每个显示对象的 laoderInfo 属性都指向文档类对象的 loaderInfo ,进度条可以直接通过自己的 loaderInfo 属性获取加载进度,从中也可以看出这种设计带便利。

监视完成的两种事件

加载完毕有两种事件: init 事件和 complete 事件。 init 事件表示 loaderInfo 对象的信息已经完全更新, swf 代码已经被初始化。此时 swf 可能还未完全下载,例如 swf 中包含大体积的视频。只有等所有数据加载完毕后才会触发 complete 事件。

当加载的 swf 很小时,选择 init complete 事件皆可,当加载体积较大的素材 swf 时,必须使用 complete 事件。

处理加载错误

资源加载与数据通信一样使用异步错误处理,由于使用 http 通信,因此也有 httpStatus 事件。当加载被卡住时,必须关闭连接重新进行加载。设置正确的间隔时间算法关系到重载机制的优劣,常用的一个算法是通过倍数加乘进行重载,例如第一次重载时间=间隔时间× 2 ,第二次重载时间=间隔时间× 4 ……。

加载的 swf 访问舞台

swf 加载完毕后,会先初始化 swf 中的代码,但此时 swf 还未被添加到加载器的显示列表,只有等到触发 Complete 后, loader 才把加载内容添加到舞台的显示列表中。如果加载的 swf 的构造函数中引用了 stage 则会报告不能访问舞台的错误。要解决此错误需要在 loaderInfo init complete 中或 addToStage 事件中初始化,也使用 render 事件延迟初始化。

在加载 swf 的构造函数中 root 属性可以访问,因为 root 引用的是加载 swf 的文档类对象而不是加载器的文档类对象。

关闭连接与卸载内容

close() 方法用于关闭正在加载的连接,可以在加载失去响应时调用。 unload() 方法用于卸载加载对象,卸载的对象不会马上消失,而是在内存中等待垃圾回收,此时加载内容已与 Loader 的引用断开,也不在 Loader 的显示列表中。如果原始内容未卸载就加载了新内容,则旧的内容被强制卸载。

为了让卸载的内容能够被垃圾回收,除了使用 unload() 方法,还必须停止内容中的所有活动对象,例如动画,声音,视频等。 Loader 类为我们提供了一个 unloadAndStop(gc:Boolean = true):void 方法, unloadAndStop() 方法先停止内容中的所有活动对象,然后再执行卸载,最后根据 gc 参数尝试强制垃圾回收。 gc 是一件耗费 cpu 的工作,如果发现卸载对象时导致很卡,可以设置 gc false 让播放器选择时机回收。

unload() unloadAndStop() 方法会触发 unload 事件,调用 unload() 方法后, contentLoadInfo 属性会建立一个新临时对象,所有的属性会被重置为 null

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值