Rus*_*uss 8 apache-flex actionscript-3
我在各种AS3代码中都看到了这种明显的魔力,但这是一个简化的例子:
package {
import flash.display.Sprite;
import flash.events.*;
import flash.net.*;
public class URLLoaderExample extends Sprite {
public function URLLoaderExample() {
var loader:URLLoader = new URLLoader();
loader.addEventListener(Event.COMPLETE, onComplete);
loader.load(new URLRequest("example.txt");
} // 'loader' should fall out of scope here!
private function onComplete(evt:Event):void {
var loader:URLLoader = URLLoader(evt.target);
trace ("Received data: " + loader.data);
//unsure if removal below is necessary (since I don't
//know where 'loader' itself is hiding!)...
// - NOTE: this removal is never in the examples!
loader.removeEventListener(Event.COMPLETE, onComplete);
}
}
}
Run Code Online (Sandbox Code Playgroud)
如代码注释中所示,loader变量应该在URLLoaderExample构造函数之后超出范围.但是......由于onComplete监听器/处理程序能够干净地接收它,它似乎仍然保持活着(不是垃圾收集).
魔术/隐藏/全局引用在哪里loader使它保持活动状态,以便它可以完成它的加载操作,然后交给onComplete监听器/回调?可以在某处看到这个参考吗?
为了帮助上下文...作为一个类似的例子,我知道loader实例将onComplete注册侦听器.我也知道我需要小心谨慎使用removeEventListener(?)以避免因搁浅的听众造成的潜在内存泄漏.我担心的是,我不明白魔法loader引用的位置以及是否(或何时)需要清理它.
这可能是loader.load()呼叫本身在loader全球范围内存在吗?
这个例子肯定容易出错,因为加载器可能在加载完成之前被垃圾收集.当您COMPLETE使用onComplete方法订阅事件时,您将从加载器创建对您的类的引用URLLoaderExample.而你需要确保GC不会毁灭装载机正在创造一个参考什么给它.
GC永远不会保证你及时清理,即使你明确杀死了所有的引用.(有关GC逻辑的资源,请参阅此文章.)但如果没有明确的引用,它可以在进程中垃圾收集加载器.如果您在使用内存的应用程序中尝试测试(并且不只是坐在那里无所事事),您可能会看到此行为.如果你尝试加载swfs而不是数据,你更有可能看到加载垃圾.
使用弱引用在这里没有帮助,因为当你这样做时,你告诉GC:"随意杀死我,调度员,我引用的,我对它没有任何遗憾." 在你的例子中,它将是:"如果它失去其他可行的引用,可以随意杀死URLLoaderExample实例",这是毫无意义的.这是关于useWeakReference的一篇好文章.
监听器不会阻止调度程序被垃圾收集.非活动对象是不再从其他活动对象引用它的对象.因此,如果对象本身具有对外部内容的引用,则不会阻止将此对象从内存中删除.
所以,简要回答一下你的问题:参考文献无处可去,你很幸运看到加载工作正常.好吧,完全准确,它是函数激活对象(在ECMA规范中称为),它用作局部变量的范围并引用它们.但无论如何,它会在方法返回时被处理掉,你永远无法获得对激活对象本身的引用(再次通过spec).
编辑更多关于谁拥有垃圾收集的话.由于评论中存在明显的误解而添加.
来自Adobe liveocs的引文:
useWeakReference:Boolean(default = false) - 确定对侦听器的引用是强还是弱.强引用(默认值)可防止您的侦听器被垃圾回收.弱参考不会.
因此,订阅事件会创建一个引用FROM dispatcher TO侦听器.与听众不同,调度员可以自由行动.监听器不会阻止调度程序被垃圾收集.调度员可以防止听众被垃圾收集,这就是为什么我们有useWeakReference.