动态加载显示内容

Flash Player 9 和更高版本,Adobe AIR 1.0 和更高版本

可以将下列任何外部显示资源加载到 ActionScript 3.0 应用程序中:

  • 在 ActionScript 3.0 中创作的 SWF 文件 — 此文件可以是 Sprite、MovieClip 或扩展 Sprite 的任何类。在 iOS 上的 AIR 应用程序中,只能加载不包含 ActionScript 字节代码的 SWF 文件。这意味着可以加载包含嵌入数据(如图像和声音)的 SWF 文件,但不能加载包含可执行代码的 SWF 文件。

  • 图像文件 — 包括 JPG、PNG 和 GIF 文件。

  • AVM1 SWF 文件 — 用 ActionScript 1.0 或 2.0 编写的 SWF 文件。(在移动 AIR 应用程序中不受支持)

使用 Loader 类可以加载这些资源。

加载显示对象

Loader 对象用于将 SWF 文件和图形文件加载到应用程序中。Loader 类是 DisplayObjectContainer 类的子类。Loader 对象在其显示列表中只能包含一个子显示对象,该显示对象表示它加载的 SWF 或图形文件。如下面的代码所示,在显示列表中添加 Loader 对象时,还可以在加载后将加载的子显示对象添加到显示列表中:

var pictLdr:Loader = new Loader(); 
var pictURL:String = "banana.jpg" 
var pictURLReq:URLRequest = new URLRequest(pictURL); 
pictLdr.load(pictURLReq); 
this.addChild(pictLdr);

加载 SWF 文件或图像后,即可将加载的显示对象移到另一个显示对象容器中,如本示例中的 container DisplayObjectContainer 对象:

import flash.display.*; 
import flash.net.URLRequest; 
import flash.events.Event; 
var container:Sprite = new Sprite(); 
addChild(container); 
var pictLdr:Loader = new Loader(); 
var pictURL:String = "banana.jpg" 
var pictURLReq:URLRequest = new URLRequest(pictURL); 
pictLdr.load(pictURLReq); 
pictLdr.contentLoaderInfo.addEventListener(Event.COMPLETE, imgLoaded);  
function imgLoaded(event:Event):void 
{ 
    container.addChild(pictLdr.content);  
}

监视加载进度

文件开始加载后,就创建了 LoaderInfo 对象。LoaderInfo 对象用于提供加载进度、加载者和被加载者的 URL、媒体的字节总数及媒体的标称高度和宽度等信息。LoaderInfo 对象还调度用于监视加载进度的事件。

下图说明 LoaderInfo 对象的不同用途 — 用于 SWF 文件的主类的实例、用于 Loader 对象以及用于由 Loader 对象加载的对象:

可以将 LoaderInfo 对象作为 Loader 对象和加载的显示对象的属性进行访问。加载一开始,就可以通过 Loader 对象的 contentLoaderInfo 属性访问 LoaderInfo 对象。加载完显示对象后,也可以通过显示对象的 loaderInfo 属性,将 LoaderInfo 对象作为已加载显示对象的属性进行访问。已加载显示对象的 loaderInfo 属性是指与 Loader 对象的 contentLoaderInfo 属性相同的 LoaderInfo 对象。换句话说,LoaderInfo 对象是加载的对象与加载它的 Loader 对象之间(加载者和被加载者之间)的共享对象。

要访问加载的内容的属性,需要在 LoaderInfo 对象中添加事件侦听器,如下面的代码所示:

import flash.display.Loader; 
import flash.display.Sprite; 
import flash.events.Event; 
 
var ldr:Loader = new Loader(); 
var urlReq:URLRequest = new URLRequest("Circle.swf"); 
ldr.load(urlReq); 
ldr.contentLoaderInfo.addEventListener(Event.COMPLETE, loaded); 
addChild(ldr); 
 
function loaded(event:Event):void 
{ 
    var content:Sprite = event.target.content; 
    content.scaleX = 2; 
}

有关详细信息,请参阅 处理事件

指定加载上下文

通过 Loader 类的 load() loadBytes() 方法将外部文件加载到 Flash Player 或 AIR 中时,可以选择指定 context 参数。此参数是一个 LoaderContext 对象。

LoaderContext 类包括三个属性,用于定义如何使用加载的内容的上下文:

  • checkPolicyFile :仅当加载图像文件(不是 SWF 文件)时才会使用此属性。如果将此属性设置为 true ,Loader 将检查策略文件的原始服务器(请参阅 网站控制(策略文件) )。只有内容的来源域不是包含 Loader 对象的 SWF 文件所在的域时才需要此属性。如果服务器授予 Loader 域权限,Loader 域中 SWF 文件的 ActionScript 就可以访问加载图像中的数据;换句话说,可以使用 BitmapData.draw() 命令访问加载的图像中的数据。

    请注意,来自 Loader 对象所在域以外的其他域的 SWF 文件可以通过调用 Security.allowDomain() 来允许特定的域。

  • securityDomain :仅当加载 SWF 文件(不是图像)时才会使用此属性。如果 SWF 文件所在的域与包含 Loader 对象的文件所在的域不同,则指定此属性。指定此选项时,Flash Player 将检查策略文件是否存在,如果存在,来自跨策略文件中允许的域的 SWF 文件可以对加载的 SWF 内容执行跨脚本操作。可以将 flash.system.SecurityDomain.currentDomain 指定为此参数。

  • applicationDomain :仅当加载使用 ActionScript 3.0 编写的 SWF 文件(不是图像或使用 ActionScript 1.0 或 2.0 编写的 SWF 文件)时才会使用此属性。加载文件时,通过将 applicationDomain 参数设置为 flash.system.ApplicationDomain.currentDomain ,可以指定将该文件包括在与 Loader 对象相同的应用程序域中。通过将加载的 SWF 文件放在同一个应用程序域中,可以直接访问它的类。如果要加载的 SWF 文件中包含嵌入的媒体,这会很有帮助,您可以通过其关联的类名访问嵌入的媒体。有关详细信息,请参阅 使用应用程序域

下面的示例在从另一个域加载位图时检查策略文件:

var context:LoaderContext = new LoaderContext(); 
context.checkPolicyFile = true; 
var urlReq:URLRequest = new URLRequest("http://www.[your_domain_here].com/photo11.jpg"); 
var ldr:Loader = new Loader(); 
ldr.load(urlReq, context);

下面的示例在从另一个域加载 SWF 时检查策略文件,以便将该文件与 Loader 对象放在同一个安全沙箱中。此外,该代码还将加载的 SWF 文件中的类添加到与 Loader 对象的类相同的应用程序域中:

var context:LoaderContext = new LoaderContext(); 
context.securityDomain = SecurityDomain.currentDomain; 
context.applicationDomain = ApplicationDomain.currentDomain; 
var urlReq:URLRequest = new URLRequest("http://www.[your_domain_here].com/library.swf"); 
var ldr:Loader = new Loader(); 
ldr.load(urlReq, context);

有关详细信息,请参阅 用于 Adobe Flash Platform 的 ActionScript 3.0 参考 中的 LoaderContext 类。

在 AIR for iOS 中加载 SWF 文件

在 iOS 设备上,对于在运行时加载和编译代码存在限制。由于这些限制,将外部 SWF 文件加载到您的应用程序中势必会有一些不同:

  • 所有包含 ActionScript 代码的 SWF 文件都必须包括在应用程序包中。不能从外部源(如通过网络)加载包含代码的 SWF。在对应用程序进行打包时,对于 iOS 设备,应用程序包中所有 SWF 文件中的所有 ActionScript 代码都将编译成本机代码。

  • 您不能加载 SWF 文件,然后卸载它再重新加载。如果这样做,会发生错误。

  • 加载到内存中然后又卸载的行为与在桌面平台上这样操作的结果相同。如果加载 SWF 文件然后卸载它,包含在该 SWF 中的所有可视资源都将从内存中卸载掉。不过,对所加载 SWF 中的 ActionScript 类的任何类引用将保留在内存中,可以在 ActionScript 代码中访问这些类引用。

  • 加载的所有 SWF 文件必须与主 SWF 文件使用相同的应用程序域。这并非默认行为,因此对于每个要加载的 SWF,您必须创建一个 LoaderContext 对象来指定主应用程序域,并将该 LoaderContext 对象传递给 Loader.load() 方法调用。如果要加载的 SWF 所处的应用程序域与主 SWF 应用程序域不同,便会发生错误。即使加载的 SWF 只包含可视资源而不包含 ActionScript 代码,也是这样。

    下例中的代码将一个 SWF 从应用程序包中加载到主 SWF 应用程序域中:

    var loader:Loader = new Loader(); 
    var url:URLRequest = new URLRequest("swfs/SecondarySwf.swf"); 
    var loaderContext:LoaderContext = new LoaderContext(false, ApplicationDomain.currentDomain, null); 
    loader.load(url, loaderContext);

对于只包含资源而不包含代码的 SWF 文件,可以从应用程序包加载,也可以通过网络加载。无论哪一种情况,都必须仍将 SWF 文件加载到主应用程序域中。

对于 AIR 3.6 之前的版本,在编译过程期间,所有代码都是从非主应用程序 SWF 中去除。只包含可视资源的 SWF 文件可以包括在应用程序包中并在运行时加载,但对于包含代码的 SWF 不是这样。如果要加载的 SWF 包含 ActionScript 代码,便会发生错误。该错误会导致应用程序中出现一个“未编译的 ActionScript”错误对话框。

另请参见

在 iOS 上的 AIR 应用程序中打包并加载多个 SWF

使用 ProLoader 和 ProLoaderInfo 类

为了帮助预加载运行时共享库 (RSL),Flash Professional CS5.5 引入了 fl.display.ProLoader 和 fl.display.ProLoaderInfo 类。这些类会镜像 flash.display.Loader 和 flash.display.LoaderInfo 类,但提供了更加一致的加载体验。

特别是,ProLoader 可帮助您加载使用 Text Layout Framework (TLF) 执行 RSL 预加载的 SWF 文件。在运行时,预加载其他 SWF 文件或 SWZ 文件(例如 TLF)的 SWF 文件需要仅供内部使用的 SWF 包装文件。SWF 包装文件会增加调用结构的复杂性,并可能产生不必要的行为。ProLoader 可以消除这种复杂关系,它可以像加载普通 SWF 文件那样加载这些文件。ProLoader 类使用的解决方法对于用户来说是透明的,不需要在 ActionScript 中执行任何特殊处理。此外,ProLoader 还可以正确加载普通 SWF 内容。

在 Flash Professional CS 5.5 和更高版本中,您可以安全地将所有 Loader 类替换为 ProLoader 类。然后,将您的应用程序导出到 Flash Player 10.2 或更高版本,以便 ProLoader 能够访问所需的 ActionScript 功能。您也可以在面向支持 ActionScript 3.0 的 Flash Player 早期版本的应用程序中使用 ProLoader。但是只有在 Flash Player 10.2 或更高版本中才能充分利用 ProLoader 的强大功能。当您在 Flash Professional CS5.5 或更高版本中使用 TLF 时,请始终使用 ProLoader。在 Flash Professional 之外的环境中,不需要使用 ProLoader。

重要说明: 对于在 Flash Professional CS5.5 和更高版本中发布的 SWF 文件,您可以始终使用 fl.display.ProLoader 和 fl.display.ProLoaderInfo 类,而不要使用 flash.display.Loader 和 flash.display.LoaderInfo。

ProLoader 类解决的问题

ProLoader 类解决了此前 Loader 类无法处理的问题。这些问题是在对 TLF 库执行 RSL 预加载的过程中产生的。具体来说,在使用 Loader 对象加载其他 SWF 文件的 SWF 文件中会碰到这些问题。解决的问题包括:

  • 加载文件和被加载文件之间的脚本处理无法按预期方式执行。 ProLoader 类会自动将加载 SWF 文件设置为被加载 SWF 文件的父项。因此,来自加载 SWF 文件的通信会直接转到被加载 SWF 文件。

  • SWF 应用程序必须主动管理加载过程。 要进行主动管理,需要实现额外的事件,例如 added removed addedToStage removedFromStage 。如果您的应用程序是面向 Flash Player 10.2 或更高版本,则 ProLoader 可消除这些额外的工作。

更新代码,使用 ProLoader 来替代 Loader

由于 ProLoader 会镜像 Loader 类,您可以轻松地在代码中切换这两个类。下面的示例显示了如何更新现有代码以使用新类:

import flash.display.Loader; 
import flash.events.Event; 
var l:Loader = new Loader(); 
 
addChild(l); 
l.contentLoaderInfo.addEventListener(Event.COMPLETE, loadComplete); 
l.load("my.swf"); 
function loadComplete(e:Event) { 
    trace('load complete!'); 
}

可将此代码更新为使用 ProLoader,如下所示:

import fl.display.ProLoader; 
import flash.events.Event; 
var l:ProLoader = new ProLoader(); 
 
addChild(l); 
l.contentLoaderInfo.addEventListener(Event.COMPLETE, loadComplete); 
l.load("my.swf"); 
function loadComplete(e:Event) { 
    trace('load complete!'); 
}