Rob Oplawar
Rob Oplawar

Reputation: 71

What can cause event-handling closures to stop working?

I'll try to be as concise as possible. I have a number of objects in an array, and I'm applying event listeners to each one using closures:

//reduced to the logic in question:
buttons.forEach(function(button:EventDispatcher, i:int, list:Array):void {
  button.addEventListener(MouseEvent.MOUSE_OVER, function(e:Event):void {
    button.filters = [button_glow_filter];
  });
});
//button-specific click handlers:
buttons[0].addEventListener(MouseEvent.MOUSE_CLICK, handle_some_action);

This works perfectly for a while, until I perform an unrelated action on the UI. It's a very complex system, so I'm not really sure what is happening. I can confirm that the unrelated action has no direct effect on the object that contains the buttons or the buttons themselves (at least, it's not changing anything via the public interfaces). The buttons still exist, and the click event listeners still work correctly because those are individually assigned real functions on the class's interface.

My question therefore is: does anyone know what can cause these closures to stop handling the MouseOver events without having any other perceptible effect on the related objects?

There are a number of ways to accomplish this MouseOver behavior, and for now I've switched to one that works, but I'd still like to know the answer to this question for future reference.

Upvotes: 0

Views: 104

Answers (1)

Rob Oplawar
Rob Oplawar

Reputation: 71

I figured out the likely culprit almost immediately after posting: garbage collection. It took just a couple of minutes to confirm. This is exactly what the useWeakReference parameter is for in the addEventListener interface; it defaults to true. By setting it to false, it prevents listeners assigned in this fashion from being garbage collected. The correct code is:

buttons.forEach(function(button:EventDispatcher, i:int, list:Array):void {
  button.addEventListener(MouseEvent.MOUSE_OVER, function(e:Event):void {
    button.filters = [button_glow_filter];
  }, false, 0, false);
});

Upvotes: 1

Related Questions