AS3:重用 URLLoader、URLRequest 和 URLVariables 实例
AS3: Reusing URLLoader, URLRequest, and URLVariables instances
我的 Flash 项目经常使用 URLLoader.load 从 Web 服务器加载内容并 post 到 php 页面。我应该重用我的 URLLoader、URLRequest 和 URLVariables 实例,还是应该每次都创建新实例?如果我每次都创建新的,是否需要以某种方式处理旧的?
您绝对不应该重复使用任何与外部操作相关的实例,并且您应该在不需要它们的那一刻彻底处理掉它们。处理这些对象的垃圾收集器 (GC) 的开销实际上与一旦您的外部操作通过共享相同的操作实例发生冲突时您可能会遇到的噩梦般的混乱几乎没有。
URLVariables 和 URLRequest 不需要任何特殊处理,只需将 null 设置为任意引用它们的变量,并确保将它们分配给局部变量的方法不会产生任何函数闭包。好吧,将 URLRequest.data 设置为 null 以打破此引用。
URLLoader,另一方面,需要稍微推一下:
- 如果URLLoader.data是一个ByteArray,那么你应该ByteArray.clear() 它(除非你需要它)。
- 将 URLLoader.data 设置为 null。
- 最初订阅所有具有弱引用的错误处理程序(addEventListener 的第五个参数设置为 true)并且不要取消订阅它们。弱键不会影响 GC 的判断,同时保留订阅可能会避免偶尔出现 未处理的错误事件 情况。
- 当然要退订所有 non-error 处理程序。
- 在所有处理程序中,首先检查 Event.target 是否是有效的 URLLoader 实例以避免处理来自dead/disposed URLLoader.
- 调用URLLoader.close()以防万一。是的,完成上述所有操作后。
下面是 class 我用来以简单方式加载东西的方法。它建立在我上面列出的相同原则之上。它允许加载 text/binary 数据并且还提供一些针对不稳定网络的证明:如果您知道请求,您可以将 repeatCount 参数设置为更高的值以提供 fail-safe 加载往往会失败有时。
用法:
// Load binary data over unstable network.
DataFiles.load("data.dat", onData, true, 10);
// Load XML file as text over a stable network or from the local storage.
DataFiles.load("setup.xml", onSetup);
function onData(source:ByteArray):void
{
if (!source)
{
// Loading failed. Error case.
}
else
{
// File is loaded normally.
}
}
function onSetup(source:String):void
{
try
{
var aSetup:XML = new XML(source);
// Process loaded XML normally.
}
catch (fail:Error)
{
// The source is either null or an invalid XML string.
// Loading is failed, basically. Error case.
}
}
实施:
package simplify
{
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.net.URLLoaderDataFormat;
public class DataFiles
{
static private var list:Vector.<DataFiles> = new Vector.<DataFiles>;
static public function load(url:String, handler:Function, binary:Boolean = false, repeatCount:int = 1):void
{
var aLoader:DataFiles = new DataFiles;
aLoader.url = url;
aLoader.binary = binary;
aLoader.handler = handler;
aLoader.repeatCount = repeatCount;
list.push(aLoader);
aLoader.start();
}
private var url:String;
private var binary:Boolean;
private var handler:Function;
private var loader:URLLoader;
private var repeatCount:int;
private function start():void
{
loader = new URLLoader;
if (binary) loader.dataFormat = URLLoaderDataFormat.BINARY;
loader.addEventListener(Event.COMPLETE, onComplete);
loader.addEventListener(IOErrorEvent.IO_ERROR, onError, false, 0, true);
loader.load(new URLRequest(url));
}
private function destroyLoader():void
{
if (!loader) return;
loader.removeEventListener(Event.COMPLETE, onComplete);
var aDead:Loader = loader;
loader = null;
aDead.data = null;
aDead.close();
}
private function onComplete(e:Event):void
{
if (e.target != loader) return;
var aResult:* = loader.data;
var aHandler:Function = handler;
destroy();
destroyLoader();
aHandler(aResult);
}
private function onError(e:IOErrorEvent):void
{
if (e.target != loader) return;
destroyLoader();
repeatCount--;
if (repeatCount >= 0)
{
start();
}
else
{
var aHandler:Function = handler;
destroy();
aHandler(null);
}
}
private function destroy():void
{
var anIndex:int = list.indexOf(this);
if (anIndex > -1) list.splice(anIndex, 1);
handler = null;
url = null;
}
}
}
我的 Flash 项目经常使用 URLLoader.load 从 Web 服务器加载内容并 post 到 php 页面。我应该重用我的 URLLoader、URLRequest 和 URLVariables 实例,还是应该每次都创建新实例?如果我每次都创建新的,是否需要以某种方式处理旧的?
您绝对不应该重复使用任何与外部操作相关的实例,并且您应该在不需要它们的那一刻彻底处理掉它们。处理这些对象的垃圾收集器 (GC) 的开销实际上与一旦您的外部操作通过共享相同的操作实例发生冲突时您可能会遇到的噩梦般的混乱几乎没有。
URLVariables 和 URLRequest 不需要任何特殊处理,只需将 null 设置为任意引用它们的变量,并确保将它们分配给局部变量的方法不会产生任何函数闭包。好吧,将 URLRequest.data 设置为 null 以打破此引用。
URLLoader,另一方面,需要稍微推一下:
- 如果URLLoader.data是一个ByteArray,那么你应该ByteArray.clear() 它(除非你需要它)。
- 将 URLLoader.data 设置为 null。
- 最初订阅所有具有弱引用的错误处理程序(addEventListener 的第五个参数设置为 true)并且不要取消订阅它们。弱键不会影响 GC 的判断,同时保留订阅可能会避免偶尔出现 未处理的错误事件 情况。
- 当然要退订所有 non-error 处理程序。
- 在所有处理程序中,首先检查 Event.target 是否是有效的 URLLoader 实例以避免处理来自dead/disposed URLLoader.
- 调用URLLoader.close()以防万一。是的,完成上述所有操作后。
下面是 class 我用来以简单方式加载东西的方法。它建立在我上面列出的相同原则之上。它允许加载 text/binary 数据并且还提供一些针对不稳定网络的证明:如果您知道请求,您可以将 repeatCount 参数设置为更高的值以提供 fail-safe 加载往往会失败有时。
用法:
// Load binary data over unstable network.
DataFiles.load("data.dat", onData, true, 10);
// Load XML file as text over a stable network or from the local storage.
DataFiles.load("setup.xml", onSetup);
function onData(source:ByteArray):void
{
if (!source)
{
// Loading failed. Error case.
}
else
{
// File is loaded normally.
}
}
function onSetup(source:String):void
{
try
{
var aSetup:XML = new XML(source);
// Process loaded XML normally.
}
catch (fail:Error)
{
// The source is either null or an invalid XML string.
// Loading is failed, basically. Error case.
}
}
实施:
package simplify
{
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.net.URLLoader;
import flash.net.URLRequest;
import flash.net.URLLoaderDataFormat;
public class DataFiles
{
static private var list:Vector.<DataFiles> = new Vector.<DataFiles>;
static public function load(url:String, handler:Function, binary:Boolean = false, repeatCount:int = 1):void
{
var aLoader:DataFiles = new DataFiles;
aLoader.url = url;
aLoader.binary = binary;
aLoader.handler = handler;
aLoader.repeatCount = repeatCount;
list.push(aLoader);
aLoader.start();
}
private var url:String;
private var binary:Boolean;
private var handler:Function;
private var loader:URLLoader;
private var repeatCount:int;
private function start():void
{
loader = new URLLoader;
if (binary) loader.dataFormat = URLLoaderDataFormat.BINARY;
loader.addEventListener(Event.COMPLETE, onComplete);
loader.addEventListener(IOErrorEvent.IO_ERROR, onError, false, 0, true);
loader.load(new URLRequest(url));
}
private function destroyLoader():void
{
if (!loader) return;
loader.removeEventListener(Event.COMPLETE, onComplete);
var aDead:Loader = loader;
loader = null;
aDead.data = null;
aDead.close();
}
private function onComplete(e:Event):void
{
if (e.target != loader) return;
var aResult:* = loader.data;
var aHandler:Function = handler;
destroy();
destroyLoader();
aHandler(aResult);
}
private function onError(e:IOErrorEvent):void
{
if (e.target != loader) return;
destroyLoader();
repeatCount--;
if (repeatCount >= 0)
{
start();
}
else
{
var aHandler:Function = handler;
destroy();
aHandler(null);
}
}
private function destroy():void
{
var anIndex:int = list.indexOf(this);
if (anIndex > -1) list.splice(anIndex, 1);
handler = null;
url = null;
}
}
}