I bet this problem has been raised before, but I want to keep track of it on my blog so here it is:
I’m building a modular application and so my target is to interface all the modules with a common interface so that they look the same to the application that loads them.
The only problem then is when you want to unload a module…
here is the scenario
If you load an external SWF file and you use only its interface to reference it, then you won’t be able to unload it properly.
But if the loader SWF knows the concrete class of the loaded swf you can then unload it. In the example above notUsedReference is never instantiated and never used to reference the loaded swf, it’s there only to force the import of MySwiftClass.
I discovered this issue while testing SwiftSuspender. At first I thought it was a problem of SwiftSuspender itself but after a couple of emails with Till (SwiftSuspender’s author) and some more testing I found out the problem described above.
Here you can find an Eclipse/FDT project folder with my tests:
swiftSuspender Unload Tests
project content:
MyExternalSwift.as: this class is the main class of the external swf file to be loaded.
MyInterface.as: the interface implemented by MyExternalSwift.as.
SwiftLoader.as: this class will load MyExternalSwift , inject some properties into it and then unload it.
SwiftLoaderForceImport.as: this class will load MyExternalSwift, reference it by its interface, force the import of MyExternalSwift, inject some properties into it and then unload it.
SwiftLoaderRemoveReferences.as: this class will load MyExternalSwift, reference it by its interface, inject some properties into it, then before unloading it will remove all the class references from the Injector using a new method I created into Injector.as to avoid the unload problem.
How to run the tests (you need to be familiar with Eclipse/FDT):
- First compile MyExternalSwift.as into MyExternalSwift.swf.
- Then in Eclipse/FDT run, in debug mode and using AIR Debug launcher (this is needed to e albe to force the garbage collector), one of the other classes. (SwiftLoader.as, SwiftLoaderForceImport.as, SwiftLoaderRemoveReferences.as)
- When running them you will see two text boxes on the stage saying that a string and a number have been injected, then after 3 seconds they should disappear as we unload MyExternalSwift.swf.
- After the swf has been unloaded press a key to force the garbage collector.
- for all the three test classes on the console panel in Eclipse you should see [UnloadSWF] …. MyExternalSwift.swf
To then prove what I said above open SwiftLoaderForceImport.as and comment out the class member m and remove the import of MyExternalSwift. (in Eclipse just reorganize imports after commenting out the line)
// private var m:MyExternalSwift;
Debug SwiftLoaderForceImport.as again and you’ll see that even when forcing the garbage collector MyExternalSwift.swf is never unloaded.
Unload issue with external SWF files that implement an interface
I bet this problem has been raised before, but I want to keep track of it on my blog so here it is:
I’m building a modular application and so my target is to interface all the modules with a common interface so that they look the same to the application that loads them.
To achive that I implement a common interface in all my SWF modules. So far so good as it works perfectly as seen on my previous blog Using SWF files that implement a specific interface.
The only problem then is when you want to unload a module…
here is the scenario
If you load an external SWF file and you use only its interface to reference it, then you won’t be able to unload it properly.
But if the loader SWF knows the concrete class of the loaded swf you can then unload it. In the example above notUsedReference is never instantiated and never used to reference the loaded swf, it’s there only to force the import of MySwiftClass.
I discovered this issue while testing SwiftSuspender. At first I thought it was a problem of SwiftSuspender itself but after a couple of emails with Till (SwiftSuspender’s author) and some more testing I found out the problem described above.
Here you can find an Eclipse/FDT project folder with my tests:
swiftSuspender Unload Tests
project content:
MyExternalSwift.as: this class is the main class of the external swf file to be loaded.
MyInterface.as: the interface implemented by MyExternalSwift.as.
SwiftLoader.as: this class will load MyExternalSwift , inject some properties into it and then unload it.
SwiftLoaderForceImport.as: this class will load MyExternalSwift, reference it by its interface, force the import of MyExternalSwift, inject some properties into it and then unload it.
SwiftLoaderRemoveReferences.as: this class will load MyExternalSwift, reference it by its interface, inject some properties into it, then before unloading it will remove all the class references from the Injector using a new method I created into Injector.as to avoid the unload problem.
How to run the tests (you need to be familiar with Eclipse/FDT):
- First compile MyExternalSwift.as into MyExternalSwift.swf.
- Then in Eclipse/FDT run, in debug mode and using AIR Debug launcher (this is needed to e albe to force the garbage collector), one of the other classes. (SwiftLoader.as, SwiftLoaderForceImport.as, SwiftLoaderRemoveReferences.as)
- When running them you will see two text boxes on the stage saying that a string and a number have been injected, then after 3 seconds they should disappear as we unload MyExternalSwift.swf.
- After the swf has been unloaded press a key to force the garbage collector.
- for all the three test classes on the console panel in Eclipse you should see [UnloadSWF] …. MyExternalSwift.swf
To then prove what I said above open SwiftLoaderForceImport.as and comment out the class member m and remove the import of MyExternalSwift. (in Eclipse just reorganize imports after commenting out the line)
Debug SwiftLoaderForceImport.as again and you’ll see that even when forcing the garbage collector MyExternalSwift.swf is never unloaded.
Can anyone explain why Flash Player does that?