Am I doing AS3 reference cleanup correctly?
In one frame of my fla file (let's call it frame 2), I load a few xml files, then send that data into a class that is initialized in that frame, this class creates a few timers and listeners.
Then when this class is done doing it's work. I call a dispatchEvent and move to frame 3. This frame does some things as well, it's initialized and creates a few event listeners and timers. When it's done, I move to frame 2 again.
This is supposed to repeat as often as I need so I need to clean up the references correctly and I'm wondering if I'm doing it correctly.
For sprites I do this.
world.removeChild(Background); // world is the parent stage
Background = null;
For instances of other classes I do this.
Players[i].cleanUp(world); // do any cleanup within the instanced class
world.removeChild(PlayersSelect[i]);
For event listeners I do this.
if(Background != null)
{
Background.removeEventListener(MouseEvent.CLICK, deSelectPlayer);
}
For timers I do this.
if(Timeout != null)
{
Timeout.stop();
Timeout.removeEventListener(TimerEvent.TIMER, queueHandler);
Timeout.removeEventListener(TimerEvent.TIMER_COMPLETE, queueCompleted);
Timeout = null;
}
And for library images I do this
if(_libImage!= null)
{
s.removeChild(Images._libImage); // s is the stage
_libImage= null;
}
And for the class itself in the main timeline, I do this
Frame2.removeEventListener("Done", IAmDone);
Frame2.cleanUp(); // the cleanup() does all the stuff above
Frame2= null;
Even if I do all this, when I get to frame 2 for the 2nd time, it runs for 1-2 seconds and then I get a lot of null reference erro开发者_开发技巧rs because the cleanup function is called prematurely.
Am I doing the cleanup correctly?
What can cause events to fire prematurely?
For me, the biggest concern is cleaning up listeners, which you are doing. To avoid any errors in listener cleanup, I always check if the item exists, and then if it has the listener; thus:
if(item)
{
if(item.hasEventListener(MouseEvent.CLICK))
{
item.removeEventListener(MouseEvent.CLICK,doSomething);
}
}
I do a simimlar check before removing child:
if(item)
{
if(this.contains(item))
{
this.removeChild(item);
item.destroy()//or whatever you code is to clear that element of its own dependencies.
item = null;
}
}
If you want to be able to let the garbage collector to clean up your objects after you set them to null. Then when you add an eventListener use a weak reference, this allows the garbage collector to collect it when its value is null. See the parameters of the addEventListener function:
addEventListener(type:String,
listener:Function,
useCapture:Boolean = false,
priority:int = 0,
useWeakReference:Boolean = false)
So for you to not have the null references, you have to set the last parameter to false.
addEventListener(MouseEvent.MOUSE_OVER, function(), false, 0, true);
instead of
addEventListener(MouseEvent.MOUSE_OVER, function());
When you have strong reference eventListeners you have to manually remove them with the removeEventLister function before removing the referenced object.
Edit: jordanx's example isn't valid, due to the fact that even though item is null, the strong reference is still there and null pointers can still take place.
精彩评论