Reputation: 4605
Assumption 1. I have utility class called Experiment
. It helps listening EnterFrame events on chosen sprites. The API looks following: Experiment.listenEnterFrame(mySprite, onEnterFrameHandler);
.
Assumption 2. I want my Experiment.listenEnterFrame
class to allow using anonymous handlers. I also want it to be memory-leak resistant (without any cleanUp()
method), i.e. reference to mySprite should be weak.
Here's the code:
package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.system.System;
import flash.utils.Dictionary;
import flash.utils.setTimeout;
public class Experiment extends Sprite
{
public function Experiment()
{
new MemoryLeakTest();
new NoMemoryLeakTest();
setTimeout(System.gc, 100);
}
private static var dict:Dictionary = new Dictionary(true);
private static function listener(event:Event)
{
dict[event.currentTarget]();
};
public static function listenEnterFrame(dispatcher:Sprite, callback:Function):void
{
dict[dispatcher] = callback;
dispatcher.addEventListener(Event.ENTER_FRAME, listener, false, 0, true);
}
}
}
import flash.display.Sprite;
internal class MemoryLeakTest extends Sprite
{
function MemoryLeakTest():void
{
Experiment.listenEnterFrame(this, function () {
trace("Memory leak");
});
}
}
internal class NoMemoryLeakTest
{
function NoMemoryLeakTest():void
{
Experiment.listenEnterFrame(new Sprite(), function () {
trace("No Memory leak");
});
}
}
In above example, the MemoryLeakTest instance is never removed - tracing "Memory leak" forever.
My interpretation of that is that callback
closure created in MemoryLeakTest
keeps reference to outer scope, which is MemoryLeakTest
instance itself. Because of this reference, MemoryLeakTest
instance can't be garbage collected.
Do you know any workaround, so I can use anonymous callbacks in my utility method without having to worry about memory freeing?
Upvotes: 1
Views: 297
Reputation: 4583
There's a known bug with Dictionaries in AS3. Instead of storing references to functions/methods, references to the closure objects are stored instead.
Which means that if you would like to store a function reference as a key in a Dictionary it will immediately be marked for GC, if the Dictionary uses weak keys, since the Dictionary is referencing the closure object and not the function itself.
This also means that if you try to store a function reference as a value in a Dictionary then the instance the closure object refers to will not be GC'd as long as the Dictionary holds the closure object. (Dictionaries have weak keys not values !) Which is exactly what is happening here.
Upvotes: 1