最近反复阅读kevincao的深入理解Flash的沙箱 – Application Domains 谈谈ActionScript垃圾回收。
结合项目中遇到的一些问题,谈谈体会。
new ApplicationDomain();是新建系统域下子域。ApplicationDomain.currentDomain;是当前程序域。new ApplicationDomain(ApplicationDomain.currentDomain);是新建当前域下的子域。
如果不是用new ApplicationDomain(ApplicationDomain.currentDomain);加载的swf,就算用外部external-library-path方式用swc通过了编译,在使用时也是获得不到定义的。因为父域无法访问子域的定义。
但是kevincao说了。 如果子SWF文件是加载到主应用程序域里的,那么这个文件是不能卸载的(前提是子SWF文件内的类定义没有被主应用程序域里定义所覆盖)。如果子SWF文件是加载到子应用程序域内(Loader的默认方式),那么这个文件是一定能够被卸载的。
所以一般都是把加载的swf放到主应用程序域的子域。这时候,如果是用外部的load类来加载,那每个swf都有一个自己独立的子域。
而用getDefinition获得类必须知道你需要的swf的在哪个域里面,不然会找不到类定义。
可以在load类里面用可以用个关联数组储存当前加载swf的域。方便随时随处getDefinition。就不怕loader已经为null或销毁了。
非当前域getDefinition获得的Class,只能new给Object类型,不然会报错滴。比如这样。var spanishGreeter:Class = spanishGreeterLoader.getClass(“es/Greeter.swf”,”Greeter”);var greeter1:Object = new spanishGreeter();
之后你可以再AS为Sprite之类,但是只有为Object时,用greeter1.foo方式访问类里面的定义时才能通过编译,不然也是会报错滴。
一定要好好理解编译期和运行期的概念。
private var _loadDomain:Object = new Object(); public function load(lib:String):void { swfLib = lib; request = new URLRequest(swfLib); var context:LoaderContext = new LoaderContext(); // context.applicationDomain = ApplicationDomain.currentDomain; context.applicationDomain = new ApplicationDomain(); _loadDomain[swfLib] = context.applicationDomain; loader.load(request, context); } public function getClass(lib:String,className:String):Class { try { return _loadDomain[lib].getDefinition(className) as Class; } catch (e:Error) { throw new IllegalOperationError(className + " definition not found in " + swfLib); } return null; }
本文遵循署名-非商业性使用共享协议,转载请注明。