0
votes

With Alchemy most builds are static swc builds. These are great for linking directly against a library, but if you try to use more than one at a time, you usually (always?) run into problems with the shared memory space. One solution I've read about is to build swf's instead and load those dynamically into their own ApplicationDomain. This would give all libraries their own memory and would allow you to load multiple Alchemy libraries. (As mentioned in these threads on the adobe forums: http://forums.adobe.com/message/3665801 and http://forums.adobe.com/message/3927791)

My question is: how do I load these swf's and get to the code inside of them? There doesn't seem to be any documentation on this issue and although I do know how to load an swf, I don't know how to get to the code because I don't have any interface to the swf.

2

2 Answers

0
votes

The problem is that we want to dynamically load the Alchemy lib, but if we build the library as a SWF it won't work (as that makes a standalone app). But we can't dynamically load a SWC-- or can we?

Here's what to do (assuming a library named mylib):

  1. Build mylib as a SWC.
  2. Unzip mylib.swc and extract the library.swf file; rename it to mylib.swf
  3. Embed mylib.swf as a binary asset
  4. At runtime, instantiate the asset as a ByteArray
  5. Pass the asset ByteArray to Loader#loadBytes
  6. When the loader fires COMPLETE, use Loader#contentLoaderInfo to get the ApplicationDomain of the loaded SWF
  7. Use ApplicationDomain#getDefinition to look up the Alchemy initializer class. e.g., cmodule.mylib.CLibInit
  8. Use the initializer like you normally would. e.g., call init, etc.
  9. ...profit!

You can embed an arbitrary number of Alchemy libraries this way, each running in its own ApplicationDomain.

0
votes

I had been trying to load the library dynamically by creating an new ApplicationDomain and passing that to the loader context for the load. What I was doing wrong was storing a reference to that ApplicationDomain and trying to get the definition from that reference. For some reason that was returning null. By implementing paleozogt's answer and altering that to load the swf dynamically, I ended up with the correct code which doesn't use a stored reference to the ApplicationDomain but gets it from the loader's contentLoaderInfo.

Here's the code if you want to load the library dynamically:

package
{
    import flash.display.Loader;
    import flash.events.Event;
    import flash.net.URLRequest;
    import flash.system.ApplicationDomain;
    import flash.system.LoaderContext;

    public class AlchemyDynamicLoad
    {
        private var _library:Object;
        private var _loader:Loader;

        public function AlchemyDynamicLoad()
        {
            var loaderContext:LoaderContext = new LoaderContext(false, new ApplicationDomain());
            var request:URLRequest = new URLRequest("../assets/mylib.swf");
            _loader = new Loader();
            _loader.contentLoaderInfo.addEventListener(Event.COMPLETE, completeHandler);
            _loader.load(request, loaderContext);
        }

        private function completeHandler(event:Event):void
        {
            // NOTE: Storing a reference to the application domain you feed to the loaderContext and then trying to get the 
            // definition from that reference is not going to work for some reason. You have to get the applicationDomain
            // from the contentLoaderInfo, otherwise getDefinition returns null.
            var libClass:Class = Class(_loader.contentLoaderInfo.applicationDomain.getDefinition("cmodule.mylib.CLibInit"));
            _library = new libClass().init();
        }
    }        
}

And here's the code if you want to embed it (paleozogt's answer):

package
{
    import flash.display.Loader;
    import flash.events.Event;

    public class AlchemyStaticLoad
    {
        [Embed(source="../assets/mylib.swf", mimeType="application/octet-stream")]
        private static var _libraryClass:Class;

        private var _library:Object;
        private var _loader:Loader;

        public function AlchemyStaticLoad()
        {
            _loader = new Loader();
            _loader.contentLoaderInfo.addEventListener(Event.COMPLETE, completeHandler);
            _loader.loadBytes(new _libraryClass());
        }

        private function completeHandler(event:Event):void
        {
            var libClass:Class = Class(_loader.contentLoaderInfo.applicationDomain.getDefinition("cmodule.mylib.CLibInit"));
            _library = new libClass().init();
        }
    }
}