Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/apache-flex/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Flash 本地计时器对象事件处理程序_Flash_Apache Flex_Actionscript 3 - Fatal编程技术网

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,这无疑是一种好的做法。这是开发人员的责任,不存在任何含糊不清的问题。