1

xml ファイルを解析し、Flex モジュールをアプリケーションに動的にロードしようとしています。ただし、毎回最後のモジュールのみをロードします。モジュールの解析と読み込みを行うシングルトン クラスがあります。クラスはこちら

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    {}

上記のクラスを次のように使用します。

moduleManager=VappModuleManager.instance;

moduleManager.handler=myhandler;

moduleManager.load();

変数「_module」のイベントリスナーに問題があることは理解していますが、解決方法がわかりません。どんな助けでも感謝します。

4

1 に答える 1

1

への呼び出しIModuleInfo.loadは非同期であるためfor、モジュールがロードされる前にループが完全に実行されます。また、ループが繰り返されるたびに、クラス レベルの_moduleプロパティが新しいインスタンスによって上書きされます。Module

READYイベントを待機し、次のモジュールが起動したときにのみロードを開始することで、各モジュールを順番にロードすることをお勧めします。また、コールバック関数を実行する代わりに、すべてのモジュールがロードされたときにイベントを発生させます。これにより、柔軟性が向上します (たとえば、複数のオブジェクトがイベントをリッスンできます)。

以下はテストされていませんが、アイデアが得られるはずです。

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"));
            }
        }
    }
}
于 2012-12-12T22:51:50.910 に答える