Anonymous functions as event handlers in a Script action - good or bad?

I came to AS3 from the JS world, and I have to admit that anonymous functions are my weakness. I use them everywhere. Now, when I came to AS3, I heard and read in many places that AS and Flash do extremely poor garbage handling, so you need to clean, delete, and delete all event handlers and event objects manually to avoid strange and inexplicable memory leaks and crashes. Not sure how much of this is true, but I would like to follow best practices from the start.

So my question is: how bad is the idea of ​​using anonymous functions as event handlers? Consider, for example, the following code:

addEventListener(Event.ENTER_FRAME, function() : void { controls.elapsed = stream.time; }); 

contorls.elapsed is a setter that, in addition to setting the current playback time for the video player, updates the entire user interface, and the stream is a NetStream object that transmits the current video.

There are many other places where an anonymous function can make the code more understandable and understandable. Check the following code for a simple fade effect for the control panel:

 public function showControls() : void { var self:Controls = this; if (!visible) { visible = true; fadeTimer = new Timer(30, 10); fadeTimer.addEventListener(TimerEvent.TIMER, function() : void { self.alpha += 0.1; }); fadeTimer.addEventListener(TimerEvent.TIMER_COMPLETE, function() : void { self.alpha = 1; }); fadeTimer.start(); } } 

I like the way it looks and fits into the code, but I'm worried about leaks. Although the Event.ENTER_FRAME handler will probably never become harmful in this form, what about timer listeners. Should I remove these listeners manually or will they be deleted automatically as soon as I set fadeTimer = null ? Is it even possible to remove listeners with anonymous functions?

+6
event-handling anonymous-function actionscript-3
source share
3 answers

There is nothing wrong with using the function methods where it works. As for memory leaks, you need to track the object in a step to see if it can be deleted.

Adding an ENTER_FRAME event ENTER_FRAME to the control ensures that the control has a reference to an anonymous function. Since the code is part of the control (or it appears), this is normal, since the anonymous function will be deleted when the control.

Adding an event handler to the timer ensures that the timer has a reference to an anonymous function. If the timer is running, it will keep the link to the anonymous function in an active state and, by combining, control enture. However, as soon as the timer has stopped, it is necessary to collect as well as function.

If all else fails, use the profiler and see!;)

+2
source share

Just noticed this post - there are a few things that may come in handy. One of them is the .callee argument (which is a reference to the current function you are in). This is useful for removing links in anonymous functions. In addition, it can be noted that you can use weak references in the addEventListener code, however this will not work for anonymous variables, since they will soon receive GC'd. For simplicity, I rewrote your code as follows: (should work - not tested)

 private function showControls() : void { if (visible) { return; } var self:DisplayObject = this; var fadeTimer= new Timer(30,10); var handler = function(e:Event) { switch (e.type) { // timer complete case TimerEvent.TIMER_COMPLETE: // remove references to this anonymous function -- for garbage collection fadeTimer.removeEventListener(TimerEvent.TIMER_COMPLETE, arguments.callee); fadeTimer.removeEventListener(TimerEvent.TIMER, arguments.callee); // break out return self.alpha = 1; // timer case TimerEvent.TIMER: return self.alpha += 0.1; } } fadeTimer.addEventListener(TimerEvent.TIMER, handler); fadeTimer.addEventListener(TimerEvent.TIMER_COMPLETE, handler); fadeTimer.start(); } 
+7
source share

I would do it something like this. And, remember to use dispose () when you want to clear the timer if it is interrupted.

 private function showControls() : void { if(_isVisible) return; // start you control here _fadeTimer = new Timer(30, 10); _fadeTimer.removeEventListener(TimerEvent.TIMER, updateFade); _fadeTimer.removeEventListener(TimerEvent.TIMER_COMPLETE, updateFadeComplete); _fadeTimer.start(); } private function updateFade(event : TimerEvent) : void { // update fade here } private function updateFadeComplete(event : TimerEvent) : void { dispose(); } private function dispose() : void { if(_fadeTimer) { _fadeTimer.stop(); _fadeTimer.removeEventListener(TimerEvent.TIMER, updateFade); _fadeTimer.removeEventListener(TimerEvent.TIMER_COMPLETE, updateFadeComplete); _fadeTimer = null; } } 
+3
source share

All Articles