Understanding when to use a weak references, versus strong references can be a confusing one. It took me awhile to fully grasp when, and when not to use one over the other. On top of that, there’s very little documentation on the LiveDocs about the subject. Under the documentation for IEventDispatcher.addEventListener(), it states:
useWeakReference:Boolean (default = false) — Determines whether the reference to the listener is strong or weak. A strong reference (the default) prevents your listener from being garbage-collected. A weak reference does not.
And here’s what they have listed for the Dictionary’s constructor:
weakKeys:Boolean (default = false) — Instructs the Dictionary object to use “weak” references on object keys. If the only reference to an object is in the specified Dictionary object, the key is eligible for garbage collection and is removed from the table when the object is collected.
Ok … thanks. So, I did some Googling, and both Ted Patrick and David Coletta have much better information on the subject.
The basic idea behind strong references and addEventListener is this: when you call addEventListener and you pass it the function that you want to be called when the event fires, the event dispatcher is actually grabbing and holding a reference to that class and function it contains. As we all know, an object won’t be garbage collected until every reference to it doesn’t exist anymore. This insures that the event dispatcher always has a reference to the function that needs to be called. However, if you’re not careful, this can be a breading ground for nasty memory leaks.
So, here’s my short list of do’s and don’ts related to strong vs weak references and event listeners:
- Always use a weak reference when adding an event listener to a class that’s a singleton, or any object that you expect to live throughout the life of your application. Remember, this applies to most of Flex’s manager classes, including the SystemManager, and any event dispatching classes that your singleton’s contain.
- Always use weak references when adding Cairngorm commands. The event dispatcher in Cairngorm is a singleton, and will always keep references to those command classes.
According to Ted, weak references are 10x slower.(True when referring to member access, but not event listening.)- It’s safe to use strong references when you’re adding an event listener to itself (i.e. the instance dispatching the event).
- You should use a weak reference when adding an event listener to the Timer class.
- Lastly, always make sure to clean up and remove any event listeners your classes are using when they’re no longer needed. I follow .NET’s approach, and I have an interface called IDisposable. This interface contains a single method called
dispose(), and inside I remove any event listeners that the class might be using. Additionally, you could clean-up any BitmapData objects you might be using, among other things. Most, if not all, of my classes that I write implement this interface, and I just make sure to calldispose()when I know the object is no longer needed.
If there’s anything else to look out for, I’d love to hear them. It’s always good to be proactive when it comes to memory leaks.
September 24th, 2007 at 6:35 pm
Ted’s post that you reference (and the speed advantages) are connected to strong typing (defining variable types and function return types), not strong references as they apply to event listeners. He does use the term(s) strong/weak reference a few times but they have different meaning in the context of his post. I could be wrong, but I am pretty sure there are no performance differences between strong and weak event listeners.
September 24th, 2007 at 7:27 pm
Thanks for the correction Ben. I see what Ted is referring to now.
September 24th, 2007 at 7:40 pm
There is some confusion over the terminology there. At one point it was suggested to call this weaker references as “weak reference” are in fact a feature of the language. The language lawyers hammered me on it. At essence here is how strong a reference is during garbage collection not the speed of member references. My article is really talking about how fast a reference can be accessed. In AS3/AVM2 if you use strong typing, the compiler maps a class to a Trait (a middle class object for mapping purposes) which results in member access that is equivalent to C++ member access speed. If you use weak typing, the result is member access is a hash table lookup and is thus highly dependent on the depth of the inheritance chain.
We do need better names for all this stuff, it gets confusing.
Great post,
Ted
April 29th, 2008 at 3:38 am
That always happens if we use “weak reference” in “addEventListener”. That risk?
I am developing an application large and I have some problems with memory leak
May 23rd, 2008 at 11:19 am
This is very cool. As someone who is new to Flex, I am glad I learned this now and not later. Thank you!
July 14th, 2008 at 8:03 pm
Hi Dan, you didn’t really spell out when not to use weak references. I got the impression that all listeners should be weak references reading this and still have no idea when not to use weak reference (or when strong reference is highly preferred over weak)
August 1st, 2008 at 7:45 am
This stuff makes my head hurt, but your article helped organize the ideas for me. I had to step back and think about what I was doing when I add an event listener to an object.
Basically, if object B adds a listener to object A, the result is that A has a
reference to B. This means that B cannot be garbage collected, even if it is no
longer used.
Now, if B is otherwise a target for garbage collection, it is certainly no
longer interested in events from A.
So, it seems to me like the weak reference option is there to protect you from
not cleaning up. Instead of removing event listeners from B, you just
rely on the weak reference because you know that if object B is otherwise
a candidate for removal, it certainly isn’t interested in events anymore.
If my analysis is correct, the only time you need a strong reference to an
event listener is when you think that this single reference to your object
is the only thing keeping it from being kicked out. But how
often does that happen? If nobody has a reference to an object, that
object is doing nothing, so it won’t be missed.
Seems to me that weak references to event listeners should always
be safe. I’m not sure that removing listeners is necessary for memory
leak prevention.
Someone please correct me if I’m wrong.
August 1st, 2008 at 4:06 pm
@Anonymous, thanks for bringing this to my attention. I’m in the process of writing a post about references in general, encompassing strong, weak, soft, and phantom references.
@Larry, I think you got it :-). When B adds a listener to A, A is holding a reference to B. Because of this, B will not be garbage collected until A is removed from memory, or B removes its listener from A, or the only references to A are weak, which triggers A to be removed from memory.
Yes, you are right when you say that removing listeners is not necessary for memory leak prevention. As long as all the listeners you add to object A are weak.
August 7th, 2008 at 12:09 pm
Do you have an example of IDisposable? How or when do you call the Dispose() function? What if your component is nested and you only want to call it when the nested components parents,parent is removed from the stage?
August 7th, 2008 at 1:44 pm
@Jdog, when working with compositions of objects, such as display objects. I usually follow a principle of the parent always managing its children. In the example you provided, the parent would call dispose() on any objects that it contains. When the dispose() method is called on the children, the children would then call dispose() on any of its children, and so on.
For Mixbook.com, I have a Page class which manages an array of text and image items. When a user deletes an image item, the page component calls ImageItem.dispose(). Inside here, I clean up any listeners to the system manager, and explicitly dispose of the BitmapData that the item is using – which frees the memory of the bitmap immediately, instead of waiting till the next garbage sweep.
Another example of dispose(), is the LoadManager class that is used throughout Mixbook.com. This class essentially controls anything from preloading images, to loading stylesheets and fonts – where each type of loadable item has its own class. Based upon where the user is in the book, requests to load items are being either added or removed from the LoadManager class. When a load item is removed from the LoadManager, the LoadManager calls dispose() on the item, which cleans up any resources its using. Such as calling Loader.close().
So the dispose() method simply acts as an interface that the parent can use to say to its children, “Hey, I know the life of this object is finished, clean up any references/resources it’s using.”