本地计时器对象事件处理程序

时间:2011-05-05 00:25:09

标签: flash 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
}

上面的代码大部分时间都可以工作,但我担心的是如果计时器被垃圾收集会发生什么?是否有可能onTimerComplete永远不会触发,因为没有其他对计时器的引用?

我知道计时器有一个内部处理程序列表,但不会阻止它被GC控制。

4 个答案:

答案 0 :(得分:1)

在网络上有一些引用从未被垃圾收集的运行计时器,e.g.

  

只是要明确:即使你没有引用Timer,也要等   当计时器运行时,它不会被垃圾收集(想想   就好像运行时保持对运行计时器的引用一样。)

     Arno Gourdol在Adobe AIR团队中的

但我无法找到权威来源。

可能最好不要依赖这种特殊行为,而是将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>

输出:

  

子画面
  计时器
  精灵
  计时器
  收集垃圾
  计时器
  计时器

答案 1 :(得分:0)

如果您的关注点是垃圾收集,您可以将计时器放入数组中以保持对其的引用吗?

var antiGarbage:Array = [];
var timer:Timer = new Timer(10000, 1);

antiGarbage[antiGarbage.length] = timer;

我不认为有一个问题,非常肯定你必须这样做:

timer.removeEventListener(TimerEvent.COMPLETE, onTimerComplete);

为计时器准备GC。

答案 2 :(得分:0)

基本上你的计时器正在做的是一次调用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
}

答案 3 :(得分:0)

我会避免使用antiGarbage数组,除非你已经看到了一个问题并且神奇地解决了它,因为它增加了额外的复杂性以便在12个月后处理。

对于事件AS3侦听器和事件调度程序,只要创建了对象,就没有遇到任何问题。需要注意的一个重要问题是创建一个对象,该对象等待(侦听)已经在初始化中早先调度过的内容,因此它错过了调用(调度事件)并无限期挂起。

如果你的Timer显示在调试器变量中它应该是滴答作响并且完成那么你应该是金色的。