trainingapplication.swf:
var moduleLoader:Loader = new Loader(); addChild(moduleLoader); // 把模块加载到系统域的子域下,与当前的应用程序域区分开 function loadModule(url:String):void { var context:LoaderContext = new LoaderContext(); context.applicationDomain = new ApplicationDomain(); moduleLoader.load(new URLRequest(url), context); }不足的是,这种定义的划分方式还不是完全隔离的。由于在同一个安全域下的内容都处于一个相同的系统域下,任何对系统域内定义的修改都将影响同一个安全域下的所有应用程序域。即使是将子SWF加载到一个单独的系统域的子域下,父SWF对系统域的更改还是会对其造成影响。
我们可以通过改动XML.prettyIndent属性来验证这一点:不管处于应用程序域层级的哪个SWF对系统域里的定义作出改变,都会影响到相同安全域下的所有文件。
parent.swf:
trace(XML.prettyIndent); // 2 XML.prettyIndent = 5; trace(XML.prettyIndent); // 5 var loader:Loader = new Loader(); var context:LoaderContext = new LoaderContext(); // 新建一个独立的应用程序域 context.applicationDomain = new ApplicationDomain(); var url:String = "child.swf"; loader.load(new URLRequest(url), context);child.swf:
trace(XML.prettyIndent); // 5所以最佳实践是对定义做的改动应该在使用后及时还原,这样可以避免对其他文件的影响。
var originalPrettyIndent:int = XML.prettyIndent; XML.prettyIndent = 5; trace(myXML.toXMLString()); XML.prettyIndent = originalPrettyIndent;同样的,你也必须留心类似这样的值有可能在你的程序之外被人所改动。
Same Domain: Runtime Shared Libraries 相同的域:运行时共享库把新增的定义增加到现有的应用程序域下可能是应用程序域最大的用处。因为继承只能把父域内的定义对子域共享,而合并定义到相同的应用程序域内则可以对所有使用这个域的SWF共享,包括父级和子级。
父应用程序域包括了子SWF的定义
运行时共享库(RSLs)正是运用了这种机制。RSLs是可以在运行时被加载的独立的代码库。通过RSLs,其他SWF可以共用其中的代码而不需要编译到自身,从而排除了冗余,减小了文件量,也让代码更容易维护。我们在主应用程序域中加载RSL,从而可以在整个程序中共享定义。
使用RSLs之前需要做些准备工作。首先,ActionScript编译器需要在发布SWF文件的时候知道哪些定义不需要被编译。
原生的Flash Player API定义就不需要编译。虽然每个SWF都需要用到原生的定义(Array,XML,Sprite等),但是这些定义只存在于Flash Player的可执行文件中,不需要也不会被编译到SWF文件中。编译器使用一个叫做playerglobal.swc的特殊SWC(预先编译的SWF类库)来识别原生定义。它包含了原生定义的接口,包括定义的名字和数据类型等。编译器通过它来编译SWF,而且不会把这些定义编译到最终的SWF中。
编译器还可以引用其他类似playerglobal.swc一样的SWC库。这些库作为“外部”类库,其中包含的定义只是用于编译,不会包含到SWF内部。
这里不详细讨论在编辑工具中如何进行库链接的设置。不同版本的编辑器的设置有些不同,具体方法请参考Flash文档。
虽然我们用SWCs来编译SWF,但实际上他们本身就是SWF文件,和其他被加载的SWF内容类似。在进行库编译的时候,同时生成了SWF和SWC文件。SWF用于运行时加载,而SWC在编译时用做外部库。