Is Loader/unload() a must for garbage collection? - actionscript-3

I'm using flash.display.Loader to load an external SWF.
When I'm done with the SWF, is it enough to manually remove all references to the loader and the SWF's content in order to free it for garbage collection? or must I also call Loader/unload()?

As it can be seen from the ASDocs of Loader
When you call the unload() method, the Loader object's contentLoaderInfo property is set to null. Any visual assets that were loaded with the SWF are unloaded and removed from memory. ActionScript class definitions in the loaded SWF remain in memory, and code in the same application domain as the loaded SWF can access instances of those classes and create new instances.
I think the best and safest way to remove it from the memory is remove all event listeners, unload and set the loader to null.

Related

AS3 - replacing / taking over base AS function

I have following scenario:
I load many external swf files (they are at same domain) dynamically inside my AS3 loader.
All of them using navigateToURL (AS3) or getURL (AS2) on some buttons, that redirects to currently no more existing old domain.
Is it possible to replace (take over) navigateToURL and getURL base AS functions to change redirect link to up to date one or at least block loaded swf from opening urls?
No. You can extend classes, and implement your own override for methods/properties, but the previously compiled swf would need to point to your new class (which it won't).
You could try catching the error thrown (perhaps with UncaughtErrorEvent) and judiciously interpret the intended URL and dispatch the appropriate commands. The ideal would still be to just recompile the loaded SWF after running a search-and-replace for the deprecated method.

Main menu on game

I have created a menu for my game with buttons and whatnot as a separate .fla file named Menu. My actual game is another .fla file called Game.fla. I was wondering what the best way would be of loading this menu before the game plays?
Thanks.
I would suggest that you create a .swc with your Menu.fla, and then just add that .swc to your Game.fla
If you are using CS6, make sure that you are setting linkage for any MovieClips you want to create instances of in your code.
In the actionscript settings on the library path tab, you can add a .swc that will be included into your .swf when compiling.
In your code, you can now create an instance and add to the display list :
// Assuming MainMenu was a movieclip with linkage set in your .swc
var mainMenu:MainMenu = new MainMenu;
addChild(mainMenu);
I should note that this does not load the .swc at runtime, it includes the .swc to your .swf at compile time. I would recommend this method over loading a .swf in most cases. Cases where I might not, is if there was a large amount of content that wasn't needed all at once. That would allow you to minimize the amount of memory you were using and reduce the .swf size of your main .swf so it loads quicker.
Anytime you are loading .swf's in at runtime you are adding another layer of complexity, so I'd not recommend it unless you do have a good reason to do so. From what you have described, this doesn't sound like a situation where I'd load an external .swf at runtime.
Load the swf output from Menu.fla and keep a check on the progressEvent from loader. Don't show the game screen until Menu.swf is completely loaded and initialized.
Some more details wrt comment from OP:
You can you http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/flash/display/Loader.html#load%28%29 to load external swfs. init Event would mark that the swf's actionscript has started executing. OTOH, complete event would tell that all the swf bytes have been loaded.

How to get Flex SWFLoader unloadAndStop to unload sound also?

public var swfLoader:SWFLoader = new SWFLoader();
[Embed(source="/some/file1.swf")]
public var file1:Class;
[Embed(source="/some/file2.swf")]
public var file2:Class;
then I do:
swfLoader.load(file1);
Later on:
swfLoader.unloadAndStop(true);
which unloads the video, but not the sound! So I add in
SoundMixer.stopAll();
Which is ok, for a while. Later on, I do:
swfLoader.load(file2);
And eventually, while watching file2, file1's audio will start playing in the background over file2's audio, with no way to stop it! What is the proper way to stop the audio of file1? The way I keep seeing is use unloadAndStop() which I am using. Unless I have to create a new swfLoader object each time?
As per Konrad's answer below, I should stop playing the sound in cleanup events, such as REMOVED_FROM_STAGE, however, how can I stop playing the sound on a swf file that is loaded with a SWFLoader? I don't see an obvious way to do that.
Solutions is bit tricky, because problem is with loaded content.
Garbage collector won't remove sound because it is still playing (so its referenced by Flash Player) but you don't have access to its sound channel (because its hidden similar to private variables in classes). That behavior is totally correct.
Solution: In loaded swf code you should stop playing that sound (in REMOVED_FROM_STAGE or other 'cleanup' event handler). Other solutions (like SoundMixer.stopAll) will work in some cases but not in all.
We often forget to clean after ours applications. Its not problem if they exist same as instance of Flash Player (removing it will clean all memory used by our swf). Problems begins when we load and unload swfs. Ignoring cleanups is fast way to memory leaks.
swfLoader.unloadAndStop(true);
Does remove the swf and the sound as well .
Works fine for me .
Even the documentation says :
Unloads an image or SWF file. After this method returns the source property will be null. This is only supported if the host Flash Player is version 10 or greater. If the host Flash Player is less than version 10, then this method will unload the content the same way as if source was set to null. This method attempts to unload SWF files by removing references to EventDispatcher, NetConnection, Timer, Sound, or Video objects of the child SWF file. As a result, the following occurs for the child SWF file and the child SWF file's display list:
Sounds are stopped.
Stage event listeners are removed.
Event listeners for enterFrame, frameConstructed, exitFrame, activate and deactivate are removed.
Timers are stopped.
Camera and Microphone instances are detached
Movie clips are stopped.

addchild from externally loaded swf in Air project

I am working on an Air app for iOS and looking for a way to load an external swf and then add/remove the movieclips in that library to the main stage.
Normally, I can use an addchild routine in the document class of the external swf which I can access from the main document class. But since document classes in externally loaded swfs are not allowed in Air deployment, I can't use this method.
Each external swf will contain up to 10 separate movieclips and there are over 25 external swf's I want to load in/remove from the main stage, all containing unique artwork/animation.
Can anyone please suggest a way to do this?
THANKS!
matt
I had same problem i also had around 10 different external swfs with code. So the easiest way for me was to compile every file to swc and included them after in project.

AS3: How to dynamically load movieclip from library without exporting in frame 1?

I have some fairly large movieclips in the library which need to be dynamically loaded at runtime. I don't want to export them all in frame 1, because that would slow down initial loading of the movie.
I tried putting an instance of each of these clips later in the timeline where they wouldn't normally be encountered. When I then tried to load one from the library dynamically, I was able to successfully get an instance of the movieclip, but its currentFrame property was 0 and I couldn't see anything on the stage. As soon as I enabled "Export in frame 1", it worked properly.
Does this old trick of putting an instance on the timeline somewhere no longer work in AS3?
I have had similar issues with large library assets and to solve my issue I would always just put the assets into separate swf's and load the external swf file when I needed it.
Check out the Loader class 'content' property - http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/flash/display/Loader.html#content
The only downfall to this is managing the assets in separate files.
I hope this helps.