Saravana
Saravana

Reputation: 303

Loading flex Modules from an XML file

I am trying to parse an xml file and load Flex modules dynamically in my application. But it loads only the last module everytime. I have a singleton class which does the parsing and loading of modules. Here is the class

package
{
import flash.events.Event;
import flash.net.URLLoader;
import flash.net.URLRequest;

import mx.controls.Alert;
import mx.events.ModuleEvent;
import mx.modules.IModuleInfo;
import mx.modules.ModuleLoader;
import mx.modules.ModuleManager;

public class VappModuleManager
{

    private static var _instance:VappModuleManager;
    private static const MODULE_PATH:String="./com/emc/vapp/"; 
    private static const MANIFEST_PATH:String="module-manifest.xml";
    private var _module:IModuleInfo;
    private var _handler:Function;
    private var loader:URLLoader; 
    public function VappModuleManager(object:SingletonEnforcer)
    {

    }

    public function set handler(handler:Function):void
    {
        _handler=handler;
    }

    public static function get instance():VappModuleManager
    {
        if(_instance==null)
        {
            _instance=new VappModuleManager(new SingletonEnforcer());               
        }

        return _instance;
    }


    public function load():void
    {
        loader = new URLLoader();
        loader.addEventListener(Event.COMPLETE, xmlLoaded);
        loader.load(new URLRequest(MANIFEST_PATH));
    }

    private function xmlLoaded(event:Event):void
    {
        Alert.show("Event Completed");
        var manifest:XML=new XML(event.target.data);
        Alert.show(manifest.module.length());

        for (var index:int=0;index<manifest.module.length();index++)
        {
            Alert.show(MODULE_PATH+manifest.module[index].@name);
            _module=ModuleManager.getModule(MODULE_PATH+manifest.module[index].@name);
            _module.addEventListener(ModuleEvent.READY,_handler);
            _module.load();
        }
    }


}
}
internal class SingletonEnforcer    {}

I use the above class as follows.

moduleManager=VappModuleManager.instance;

moduleManager.handler=myhandler;

moduleManager.load();

I understand the problem is with eventlistener for variable "_module" but dont know how to solve it. Any help appreciated.

Upvotes: 1

Views: 380

Answers (1)

net.uk.sweet
net.uk.sweet

Reputation: 12431

The call to IModuleInfo.load is asynchronous so your for loop has run completely before any of the modules have loaded. Also, your class level _module property is overwritten by a new Module instance each time the loop iterates.

I'd suggest loading each module sequentially by waiting for the READY event and initiating the load of the next module only when it has fired. I'd also fire an event when all the modules are loaded instead of executing a callback function as this will give you more flexibility (multiple objects can listen for an event for example).

The following isn't tested, but should give you the idea:

package
{
    import flash.events.Event;
    import flash.net.URLLoader;
    import flash.net.URLRequest;

    import mx.controls.Alert;
    import mx.events.ModuleEvent;
    import mx.modules.IModuleInfo;
    import mx.modules.ModuleLoader;
    import mx.modules.ModuleManager;

    public class VappModuleManager
    {

        private static var _instance:VappModuleManager;

        private static const MODULE_PATH:String="./com/emc/vapp/"; 
        private static const MANIFEST_PATH:String="module-manifest.xml";

        private var loader:URLLoader; 
        private var manifest:XML; 
        private var loadCount:int = 0; // track loaded modules

        public function VappModuleManager(object:SingletonEnforcer)
        {

        }

        public static function get instance():VappModuleManager
        {
            if(_instance==null)
            {
                _instance=new VappModuleManager(new SingletonEnforcer());               
            }

            return _instance;
        }


        public function load():void
        {
            loader = new URLLoader();
            loader.addEventListener(Event.COMPLETE, xmlLoaded);
            loader.load(new URLRequest(MANIFEST_PATH));
        }

        private function xmlLoaded(event:Event):void
        {
            manifest =new XML(event.target.data);

            // load the first module
            loadModule();
        }

        private function loadModule() {
            // Use a locally scoped variable to avoid writing over the previous instance each time.
            // You could push these onto an array if you need to be able to access them later
            var module:IModuleInfo = ModuleManager.getModule(MODULE_PATH+manifest.module[loadCount].@name);
            module.addEventListener(ModuleEvent.READY, moduleReadyHandler);
            module.load();
        }

        private function moduleReadyHandler(event:ModuleEvent) {
            // Remove the event listener on the loaded module
            IModuleInfo(event.target).removeEventListener(ModuleEvent.READY, moduleReadyHandler);

            loadCount ++;

            // Are there still modules in the manifest to load?            
            if (loadCount < manifest.module.length()) {
                // Yes... load the next module
                loadModule();
            } else {
                // No... we're all finished so dispatch an event to let subscribers know
                dispatchEvent(new Event("complete"));
            }
        }
    }
}

Upvotes: 1

Related Questions