模块可以让你将程序分割成几个片段或单元。主程序或“壳”,可以动态的加载其它需要的模块,不会在启动时加载所有的模块,也不会加载任何用户尚未进行交互的模块。
模块是可以被一个程序加载和卸载的swf文件,从而释放内存和资源。模块不能独立于程序运行,但是可以在任意数量的程序间共享。
优点:
1.更小的初始阶段swf文件下载量
2.更短的加载时间
3.更好的封装程序
模块化可以分为两种类型:模块和运行时共享库
- 模块(Model)
- 运行时共享库(RSL)
ApplicationDomain是存放AS3定义(包括类、方法、接口)的容器。使用Loader类加载swf时可以通过指定Application参数将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的类似结构:

- 加载到子域(模块)
- 加载到同域(运行时共享库)
- 加载到新域(独立运行的程序或模块)
模块加载到同域不是一样可以吗?为何要加载到子域呢?好处就在于,卸载一个加载到子域的模块时,只要确保清除所有到该模块的引用,模块的所有类定义将被垃圾回收(Garbage Collection)。
有两种方式可以访问 ApplicationDomain :
- ApplicationDomain.currentDomain
- LoaderInfo类的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的自定义事件抛出参数。主程序可以把模块的自定义事件也编译进去,或者让监听模块事件的函数接受一个Object参数,以获取其动态属性。代码: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变量取出此方法。
1999

被折叠的 条评论
为什么被折叠?



