教程:深入理解Flash的沙箱 – Application Domains (5)

Compiling a Shared Library


编译器使用SWCs共享库,SWF共享库在运行时加载

另一个准备工作需要编写代码。使用外部库的时候,发布的SWF中不包含库中的定义。如果Flash Player尝试运行其中代码,就会产生核查错误,整个SWF基本上就瘫痪了。

Flash Player会在类第一次使用的时候校验其定义。如果应用程序域中不包括该定义,那么校验错误就会产生。

实际上缺少定义产生的错误有两种。校验错误是两种之中最糟的,表示类无法正常工作的灾难性失败。另一种是引用错误,当某种数据类型被引用但是却不可用的情况下发生。虽然缺失定义也会造成引用错误,但这种错误只会在已经经过核查的类内部打断代码执行的正常过程。

var instance:DoesNotExist; // VerifyError: Error #1014: Class DoesNotExist could not be found. // 当Flash Player校验包含该定义的类时发生校验错误 var instance:Object = new DoesNotExist(); // ReferenceError: Error #1065: Variable DoesNotExist is not defined. // 当代码执行到这一行的时候发生引用错误

主要的区别在于校验错误与类定义有关,而引用错误与代码执行相关。在类内部的代码要执行之前,必须要先通过校验。上面的例子中instance对象声明为Object类型,校验可以正常通过(只是在执行的时候就会遇到引用错误)。

Note: Strict Mode 注意:严格模式

外部库是引用定义而不需将其编译到SWF中的一种方法。另一种方法是关闭严格模式,这将大大放宽了对变量使用的检查。对于类的使用来说,你可以引用一个不存在的类而不会引起编译器报错。你不能直接把不存在的类用作变量类型(这样做会在运行时产生校验错误),但是你可以像上面的“引用错误”例子中那样去引用。在非严格模式下,编译器也许会检测不到一些可能发生的错误,所以通常不建议用这种模式。

使用了RSLs的SWF文件必须保证先加载好RSLs,才能使用这些外部定义。我们应该在主应用程序开始执行之前用一个预加载器来加载RSLs。

下面演示了一个SWF加载包含Doughnut类的外部RSL的例子。虽然在SWF中直接引用了这个类,但是它却是编译在外部库中,并通过SWC的方式来引用的。RSL在Doughnut类第一次使用之前就被加载进来,所以不会造成校验错误。

Doughnut.as (编译为 doughnutLibrary.swc 和 doughnutLibrary.swf):

package { import flash.display.Sprite; public class Doughnut extends Sprite { public function Doughnut(){ // draw a doughnut shape graphics.beginFill(0xFF99AA); graphics.drawCircle(0, 0, 50); graphics.drawCircle(0, 0, 25); } } }

ShapesMain.as (Shapes.swf的主类):

package { import flash.display.Sprite; public class ShapesMain extends Sprite { public function ShapesMain(){ // 虽然并没有编译到Shapes.swf中, // 但是我们通过doughnutLibrary.swc外部库 // 可以获得对Doughnut类的引用 var donut:Doughnut = new Doughnut(); donut.x = 100; donut.y = 100; addChild(donut); } } }

Shapes.swf (RSL loader):

var rslLoader:Loader = new Loader(); rslLoader.contentLoaderInfo.addEventListener(Event.INIT, rslInit); // 把RSL中的定义加载到当前应用程序域中 var context:LoaderContext = new LoaderContext(); context.applicationDomain = ApplicationDomain.currentDomain; var url:String = "doughnutLibrary.swf"; rslLoader.load(new URLRequest(url), context); function rslInit(event:Event):void { // 只有当RSL中的定义导入到当前应用程序域以后 // 我们才能用其中的Doughnut定义通过ShapesMain类的校验 addChild(new ShapesMain()); }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zysfsp.html