现在的位置: 首页 > 综合 > 正文

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

2012年07月31日 ⁄ 综合 ⁄ 共 4908字 ⁄ 字号 评论关闭

对于一个大型应用程序,资源和代码不可能全部包含在一个
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

抱歉!评论已关闭.