该帖已经被评为隐藏帖
|
|
---|---|
作者 | 正文 |
发表时间:2010-01-28
当程序越来越大,我们需要把它拆分成多个swf,在需要的时候动态加载。拆分时应该尽量把不同的类编译进唯一的swf,避免因swf文件增多而使整个程序的文件尺寸增大。按此原则可以拆分出以下两种swf,借助 ApplicationDomain 共享其代码和资源。
ApplicationDomain 是存放AS3定义(包括类、方法、接口等)的容器。使用Loader类加载swf时可以通过指定 ApplicationDomain 参数将swf加载到不同的域(Domain):
var
loader
:
Loader
=
new
Loader
()
;
var context : LoaderContext = new LoaderContext () ; /* 加载到子域(模块) */ context . applicationDomain = new ApplicationDomain ( ApplicationDomain . currentDomain ) ; /* 加载到同域(共享库) */ context . applicationDomain = ApplicationDomain . currentDomain ; /* 加载到新域(独立运行的程序或模块) */ context . applicationDomain = new ApplicationDomain () ; loader . load ( new URLRequest ( " loaded.swf " ) , context ) ;
ApplicationDomain使用类似于显示列表(DisplayList)的树形结构。 相对于舞台(Stage) ,可以认为
ApplicationDomain 最根部的是系统域(system domain),包含 Flash Player
核心类定义。主程序所在的域(以下简称主域)就是它唯一的子域,类似于Stage下的文档类(Document Class)。
this
.
stage
.
addChild
(
mySprite
)
;
this . addChild ( myMC ) ; this . addChild ( myShape ) ; 运行后的显示列表:
饿
ApplicationDomain 的类似结构:
2
模块加载到同域不是一样可以吗?为何要加载到子域呢?好处就在于,卸载一个加载到子域的模块时,只要确保清除所有到该模块的引用,模块的所有类定义将被垃圾回收(Garbage Collection)。
ApplicationDomain 的 hasDefinition() 方法判断某定义是否存在,getDefinition() 方法获取指定的定义。下面以一个 例子
来介绍 ApplicationDomain 的具体用法和应用程序的拆分。
private
function
showModule
(
p_module
:
IModule
)
:
void
{ if ( this . m_moduleList [ 0 ] == " login.swf " ) { p_module . show ( this ) ; p_module . addEventListener ( " login " , this . onLogin ) ; } else { p_module . show ( this , this . m_userName ) ; } } 模块“继承”了主程序和共享库的所有类和资源,可以通过 ApplicationDomain.currentDomain.getDefinition() 来获取相应的类。注意获取不存在的类会抛出一个 ReferenceError。
protected
function
getClass
(
p_name
:
String
)
:
Class
{ try { return ApplicationDomain . currentDomain . getDefinition ( p_name ) as Class ; } catch ( p_e : ReferenceError ) { trace ( " 定义 " + p_name + " 不存在 " ) ; return null ; } return null ; } 登录模块获取库中的界面元素,并在点击按钮后抛出事件。Event类不允许带参数,必须使用继承Event的自定义事件抛出参数。主程序可以把模块的自 定义事件也编译进去(这样就增大了整个程序的文件尺寸),或者让监听模块事件的函数接受一个Objcet参数,以获取其动态属性。
private
function
onLogin
(
p_e
:
Object
)
:
void
{ this . m_userName = p_e . userName ; var login : IModule = p_e . currentTarget ; login . removeEventListener ( " login " , this . onLogin ) ; login . dispose () ; this . loadSwf () ; } 主程序收到事件之后卸载注册模块,加载“结果模块”到子域,并将登录模块传出的”userName”参数传给结果模块。
public
function
show
(
p_parent
:
DisplayObjectContainer
, ...
rest
)
:
void
{ var libClass : Class = this . getClass ( " net.eidiot.appDomainDemo.Libaray " ) ; if ( libClass != null ) this . initUi ( libClass , rest ) ; } override protected function initUi ( p_libClass : Class , p_rest : Array = null ) : void { this . addUi ( this . getClass ( p_libClass . BG_NAME ) , " 结果 " ) ; var resultFunc : Function = p_libClass . getResult ; var userName : String = p_rest [ 0 ] ; this . addChild ( resultFunc ( userName )) ; } 注意initUi()方法分别使用了共享库中Libaray类的静态属性BG_NAME和静态方法getResult()。但是直接调用此静态方法会报错,可以先用 resultFunc 变量取出此方法。详细内容请参考 源代码 。
这篇文章在杜增强的博客看到,感谢他的分享。看完受益非浅! 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
浏览 3207 次