Flex の Module 開発 (2) - ロード側
少し間が開いてしまいましたが、前回 作成したモジュールを利用するコード(シェル)を作成していきます。
MXML からロード
MXML でロードするには <mx:ModuleLoader> タグを利用します。
次のように url プロパティでモジュールの場所を指定し、loadModule() メソッドを呼べばロードできます。
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml"> <mx:Script> <![CDATA[ private function load(ml:ModuleLoader):void { ml.url = "MyModuleA.swf"; ml.loadModule(); } private function onReady(ml:ModuleLoader):void { var myModule:IMyModule = ml.child as IMyModule; if(myModule) { myModule.setText("loaded"); } } ]]> </mx:Script> <mx:ModuleLoader id="ml1" ready="onReady(ml1)"/> <mx:Button click="load(ml1)" label="load"/> <mx:ModuleLoader id="ml2" ready="onReady(ml2)"/> <mx:Button click="load(ml2)" label="load"/> </mx:Application>
モジュールのダウンロードが完了すると、ModuleLoader 内にロードした SWF が addChild されます。ModuleLoader には同時に1つのモジュールしかロードできません。複数のモジュールをロードするためには、モジュールの個数分の ModuleLoader を作成してください。
1度ロードしたモジュールは ModuleManager によりキャッシュされ、2回目以降の loadModule() はネットワークアクセスなしに行うことができます。キャッシュを削除するには、ModuleLoader クラスの unloadModule() メソッドを呼びます。
ちなみに、ModuleLoader クラスは VBox を継承したコンテナです。ModuleLoader クラスが UIComponent や Container ではなく、VBox を継承しているところに違和感を感じた方もいるかもしれません。これは、ModuleLoader クラスを継承して、ロードするための情報を表示させるときに便利だからです。具体例は Roger Gonzalez: My MAX preso... からダウンロードできる demos/Insurance/MyModuleLoader.mxml をご覧ください。この例では、MoModuleLoader の中に、ロード開始のボタンとロード状況を表すプログレスバーなどを表示しています。
ActionScript からロード
ActionScript からロードする場合も、MXML の場合と同様です。ModuleLoader クラスのインスタンスを生成し、loadModule() を呼び出せば OK です。
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" applicationComplete="init()"> <mx:Script> <![CDATA[ import mx.events.ModuleEvent; import mx.modules.*; private function init():void { var ml:ModuleLoader = new ModuleLoader(); ml.url = "MyModuleA.swf"; addChild(ml); ml.addEventListener("ready", function(e:ModuleEvent):void { onReady(ml); }); ml.loadModule(); } // onReady 関数は先ほどと同様 ]]> </mx:Script> </mx:Application>
ここでは、さらに掘り下げて ModuleLoader を使わない方法を紹介しましょう。ModuleLoader は内部で ModuleManager や IModuleInfo といったクラス利用しています。これらのクラスに直接アクセスすることで、多少煩雑にはなりますが、より細かくモジュールの動作を制御することができます。
以下のコードをご覧ください。
<?xml version="1.0" encoding="utf-8"?> <mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" applicationComplete="init()"> <mx:Script> <![CDATA[ import flash.display.DisplayObject; import flash.display.Sprite; import mx.events.ModuleEvent; import mx.modules.*; private function init():void { var module:IModuleInfo = ModuleManager.getModule("MyModuleA.swf"); module.addEventListener("ready", readyHandler); module.load(null); } private function readyHandler(e:ModuleEvent):void { var module:IModuleInfo = e.module; var d1:DisplayObject = module.factory.create() as DisplayObject; addChild(d1); var mod1:IMyModule = d1 as IMyModule; if(mod1) { mod1.setText("1"); } var d2:DisplayObject = module.factory.create() as DisplayObject; addChild(d2); var mod2:IMyModule = d2 as IMyModule; if(mod2) { mod2.setText("2"); } } ]]> </mx:Script> </mx:Application>
この例では、ModuleManager.getModule() メソッドを利用して、IModuleInfo を取得しています。まず、IModuleInfo 経由でモジュールのロードが完了の通知を受け取ります。イベントハンドラでは、factory.create() を利用してインスタンスを生成し、これを addChild しています。
1つのモジュールから複数のインスタンスを生成しているところがポイントです。
まとめ
モジュールをロード側する方法を紹介しました。大きく分けて次の2つの方法があります。
- 簡単に実装するなら ModuleLoader を使う
- 少し込み入った使い方をするなら ModuleManager や IModuleInfo を使う

