Flash 本地计时器对象事件处理程序
我在类函数中有以下代码:Flash 本地计时器对象事件处理程序,flash,apache-flex,actionscript-3,Flash,Apache Flex,Actionscript 3,我在类函数中有以下代码: public function foo():void { var timer:Timer = new Timer(10000,1); timer.addEventListener(TimerEvent.TIMER_COMPLETE,onTimerComplete); timer.start(); } public function onTimerComplete(e:TimerEvent):void { // do stuff } 上面的
public function foo():void
{
var timer:Timer = new Timer(10000,1);
timer.addEventListener(TimerEvent.TIMER_COMPLETE,onTimerComplete);
timer.start();
}
public function onTimerComplete(e:TimerEvent):void
{
// do stuff
}
上面的代码大部分时间都在工作,但我关心的是,如果计时器被垃圾收集,会发生什么?onTimerComplete是否可能永远不会触发,因为没有其他对计时器的引用
我知道timer有一个内部处理程序列表,但这不会阻止它被GC’ed。如果您关心的是垃圾收集,您可以将timer放入一个数组中以保留对它的引用吗
var antiGarbage:Array = [];
var timer:Timer = new Timer(10000, 1);
antiGarbage[antiGarbage.length] = timer;
但我不认为有什么问题,我很确定你必须这样做:
timer.removeEventListener(TimerEvent.COMPLETE, onTimerComplete);
为了让计时器为GC做好准备。基本上,计时器所做的是调用onTimerComplete方法一次,所以为什么要关心它是否为GCed。
在任何情况下,您都在使用非常接近JavaScipt闭包的东西。闭包是一个失去作用域的函数。当某个对象失去作用域时,将很难对其进行GC,特别是因为您仍然有一个事件侦听器连接到它。在您的情况下没有意义,因为它只运行一次。
好的编码实践是在处理完对象后将其清空。
另外,关于您的代码还有一件事。
这是错误的
timer.addEventListener(TimerEvent.COMPLETE,onTimerComplete);
应该是
timer.addEventListener(TimerEvent.TIMER_COMPLET,onTimerComplete);
如果将计时器对象移动到类作用域,它将不会被GCed
public var timer:Timer = new Timer(10000,1);
public function foo():void
{
this.timer.addEventListener(TimerEvent.TIMER_COMPLETE,this.onTimerComplete);
this.timer.start();
}
public function onTimerComplete(e:TimerEvent):void
{
// do stuff
}
我会避免使用antiGarbage数组,除非你已经看到了一个问题,并且它神奇地解决了这个问题,因为它增加了处理12个月后的额外复杂性 只要创建了对象,事件AS3侦听器和事件分派器就无法相互连接,我没有遇到任何问题。需要注意的一个重要问题是创建一个对象,该对象一直在等待(侦听)在初始化过程中已调度的内容,因此它错过了调用(调度事件)并无限期挂起
如果您的计时器在调试器变量中显示,而它本应在滴答滴答并完成,那么您应该是金色的。网络上有一些关于运行计时器从未被垃圾收集的参考: 只是想澄清一下:即使你没有提到计时器,只要 当计时器运行时,它不会被垃圾收集(想想 这就好像运行时保留了对运行计时器的引用一样) 由AdobeAIR团队的Arno Gourdol撰写 但我还没有找到权威的消息来源 不过,最好不要依赖这种特殊行为,而是将
timer
设为类级变量
暗示事件侦听器阻止计时器被垃圾收集的答案是不正确的。引用是从计时器到侦听器函数(onTimerComplete
),因此如果计时器是可访问的,则侦听器函数不会被垃圾收集,反之亦然。这很容易测试:
<?xml version="1.0" encoding="utf-8"?>
<s:Application
xmlns:s="library://ns.adobe.com/flex/spark"
creationComplete="application1_creationCompleteHandler(event)">
<fx:Script>
<![CDATA[
private var _gcTimer:Timer;
protected function application1_creationCompleteHandler(event:FlexEvent):void {
var timer:Timer = new Timer(30, 4);
timer.addEventListener(TimerEvent.TIMER, onTimer, false, 0, true);
var sprite:Sprite = new Sprite();
sprite.addEventListener(Event.ENTER_FRAME, onSprite, false, 0, true);
_gcTimer = new Timer(59, 1);
_gcTimer.addEventListener(TimerEvent.TIMER, garbageCollect);
timer.start();
_gcTimer.start();
}
private function onTimer(event:TimerEvent):void {
trace("timer");
}
private function onSprite(event:Event):void {
trace("sprite");
}
]]>
</fx:Script>
</s:Application>
输出:
雪碧计时器
雪碧
计时器
收集垃圾
计时器
计时器
我担心的是,如果计时器的延迟太长,比如说数千秒,是否有可能计时器被垃圾收集,而onTimerComplete从未被调用。在移除事件侦听器之前,不应该对其进行GCD。你确定吗?这篇文章:声明侦听器不会阻止dispatchers被GC'ed。并且仔细想想,这些函数所在的类(以及该函数的父类和…)在计时器消失之前也不会被GCed。因此,正如您所看到的,您的方法是一种不好的做法。将其作为类级变量,并在以后不再需要时将其设为null,这无疑是一种好的做法。这是开发人员的责任,不存在任何含糊不清的问题。