编译器使用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()); }