Following my post yesterday about the addition of Loader.unloadAndStop to the Flash Player 10 API, I chatted with Werner Sharp, who is one of the Adobe engineers that worked on the feature (and an all round good guy). Following that discussion, I thought it would be helpful to post a summary of what I know about it, and disseminate some of the information Werner provided.
The unloadAndStop method was added in response to challenges ActionScript developers were facing with halting loaded SWF content, and removing it from memory. These issues were detailed in an article I posted in early April titled “Failure to Unload: Flash Player 9’s Dirty Secret“.
This API addition is not a magic bullet for solving all of the listed problems. What it does do, is attempt to prepare the loaded content for collection, and then hint to the Garbage Collector that it should initiate a collection pass. You can prevent the latter by passing false as the first parameter. It is still easy to get a SWF stuck in memory, but it is much harder to do accidentally.
Here is the list of things that unloadAndStop does to prepare loaded SWFs for collection:
- Stops all MovieClips
- Stops all sounds playing/streaming
- Stop/removes all Timer objects
- Remove all global listeners for enterFrame, exitFrame, frameconstructed, activate, deactivate
- Remove all stage listeners that have been created by the child.
- Closes all NetConnection/NetStream
- Removes AS3 fonts from the global font table
- Stops sockets, xmlsockets, filereference downloads, other downloading objects (grandchildren SWF), etc.
- Frees bitmap related to cacheAsBitmap/filter, etc.
Note that all of the above are run recursively, so they will also apply to any nested children, including other loaded SWFs.
There have been a few early questions about unloadAndStop that I will try to answer:
Why wasn’t this functionality just built into the unload method?
There are a couple good reasons for this. The first is backwards compatibility. This is a pretty major change in real functionality, if not expected functionality, and changing it could break a lot of content. This is also a very invasive function, and could have weird effects in some circumstances. For instance, if you loaded a SWF, made a reference to a child of that SWF, called unloadAndStop, then reparented that child into your main application things could get weird because that child DisplayObject has already been “stopped”.
What types of things will keep the SWF in memory?
This API does not null external references to your SWF, or to elements in the SWF – doing so would be very processor intensive in large projects. As such, any hard references to the SWF or objects within it will prevent collection. For example, if your main application were to reference a movie clip in the loaded SWF such as:
var myFunClip:MovieClip = myLoader.content.funClip;
You can also do this inadvertently with events. unloadAndStop will remove listeners that the loaded SWF created on the stage (for listening to MOUSE_MOVE events, for example), but not in other locations. Something as simple as the following code in your SWFs main timeline can prevent it from unloading, because it will create a hard reference back to it:
As you can see, unloadAndStop isn’t perfect, but in conjunction with fixes for the bugs I mentioned in my article, it’s a solid step in the right direction. That doesn’t mean I’m going to stop pushing for content sandboxing and explicit unloading though. 🙂