5
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Robotlegs2を用いたFlash開発

Last updated at Posted at 2016-02-02

tosikさんが投稿した記事を参考に、Robotlges2を使用したサンプルアプリケーションを作成しました。
Robotlegs2のGitHubはコチラ

Robotlegs2とは

FlashでDIコンテナを実装するためのMVCS(Model-View-Controller-Service)フレームワークライブラリです。

Robotlegsの利点

DIコンテナのフレームワークはいくつかありますが、RobotlegsがDIコンテナを実装する上で必要最低限の機能をそろえており、他のライブラリに比べて一番学習コストが低いです。
DIコンテナをとりあえず試用したい、勉強したい場合にオススメです。

※新卒2人に簡単にRobotlegs2の概要と実装方法を教えた後、約2週間ほどでライブラリを使いこなしていました。

実装サンプル

「テスト表示」のテキストをクリックすると「変更しました」と表示する単純なアプリです。

クリック前.png

クリック後.png

今回のサンプルはここからダウンロードできます。

※サンプルはMVCモデルで実装しています。
FlashDevelopを使用しています。

サンプルコードの説明

Main

Main.as
	/**
	 * フレームワーク Robotlegs2 サンプルプロジェクト
	 * as3であればGraphics,Stage3D、Flexで使用可能
	 * このプロジェクトはgraphicsで記載
	 * 
	 * @author ogino
	 */
	public class Main extends Sprite 
	{
		
		//-----------------------------------------------------
		//コンポーネント
		//-----------------------------------------------------			
		
		/**
		 * コンストラクタ
		 */
		public function Main():void 
		{
			if (stage) init();
			else addEventListener(Event.ADDED_TO_STAGE, init);
		}
		
		//-----------------------------------------------------
		//イベントハンドラー
		//-----------------------------------------------------			
		
		/**
		 * 初期化
		 * 
		 * @param	e Event
		 */
		private function init(e:Event = null):void 
		{
			removeEventListener(Event.ADDED_TO_STAGE, init);
			
			// Robotlegs2を起動するための設定
			// MVCSBundleをセット
			// コンフィグクラスをセット
			// 最後にコンテキストビューをセットし、初期化処理を実行
			
			var context:Context = new Context();
			// おまじない
			context.install(MVCSBundle);
			// コンフィグクラスをセット
			context.configure(MainConfig);
			// コンテキストビューとしてこの画面をセット
			context.configure(new ContextView(this));
			// Robotlegs2初期化
			context.initialize();
		}
		
	}

Robotlegs2を利用するにあたり、以下は必ず決まった書き方(おまじない)になります。

var context:Context = new Context();
context.install(MVCSBundle);
context.configure(MainConfig);
context.configure(new ContextView(this));
context.initialize();

MVCSを実現するだけなら、MVCSBundleをinstallすれば大丈夫です。

context.install(MVCSBundle);

ContextViewにドキュメントクラスを登録します。

context.configure(new ContextView(this));

ドキュメントクラスでなくても大丈夫ですが、変な動作するのも怖いのでinitialzeメソッドを呼び出すクラスを登録するのが無難です。


コンフィグクラスは連続で設定することも可能です。

context.configure(MainConfig).
     configure(ServiceConfig).
     configure(SocketServiceConfig);

最後にinitializeを呼び出します。これで初期化は終了です。

context.initialize();

Config

MainConfig.as
	/**
	 * メイン画面のコンフィギュレーションを行うクラス
	 * 
	 * このクラスで以下の設定を実行しています。
	 * 	・UserModel はシングルトンである
	 * 	・UserView の対になるメディエータは UserViewMediator である
	 *  ・メディエーターでUserChangeEvent.USER_CHANGEが呼ばれた場合、UserCommondを実行する
	 * 
	 * @author ogino
	 */
	public class MainConfig implements IConfig 
	{
	
		//-----------------------------------------------------
		//コンポーネント
		//-----------------------------------------------------			
		
		/** 画面 */
		private var userView:UserView = new UserView();		
		
		//-----------------------------------------------------
		//プロパティ
		//-----------------------------------------------------			
		
		[Inject]
		/** インジェクター */
		public var injector:IInjector;
		
		[Inject]
		/** メディエーターマップ */
		public var mediatorMap:IMediatorMap;
		
		[Inject]
		/** イベントコマンドマップ */
		public var commandMap:IEventCommandMap;				
		
		[Inject]
		/** コンテキストビュー */
		public var contextView:ContextView;
		
		//-----------------------------------------------------
		//メソッド
		//-----------------------------------------------------			
		
		/**
		 * コンフィギュレーション実行
		 */
		public function configure():void 
		{
			// おまじない
			
			// UserModel はシングルトンである
			injector.map(UserModel, "modelName").asSingleton();
			injector.map(UserModel).asSingleton();
			
			// UserView の対になるメディエータは UserViewMediator である
			mediatorMap.map(UserView).toMediator(UserViewMediator);
			
			// メディエーターでUserChangeEvent.USER_CHANGEが呼ばれた場合、UserCommondを実行する
			commandMap.map(UserChangeEvent.USER_CHANGE).toCommand(UserCommand);
			
			// このような形で値を注入することも可能
			//var user:UserModel = new UserModel();
			//injector.map(UserModel, "modelName").toValue(user);			
			
			// おまじないを設定すると、下記の処理が出来る
			
			// 画面を切り替える このプロジェクトは一つしか画面がないので、このメソッドで初期化処理を実行
			contextView.view.addChild(userView);
			
			// DIコンテナからモデルを取得
			var m:UserModel = injector.getInstance(UserModel, "modelName");
			m.name = "テスト表示";
		}
		
	}

Configは必ずrobotlegs.bender.framework.api.IConfigをimplementsする必要があります。

public class MainConfig implements IConfig

Configクラスを実装する上で、以下のプロパティを設定する必要があります。

[Inject]
public var injector:IInjector;
[Inject]
public var mediatorMap:IMediatorMap;		
[Inject]
public var commandMap:IEventCommandMap;	

この3つはRobotlegs側が自動的に注入されるため、おまじないはありません。
※Injectタグをつけるプロパティは必ずpublicにしてください。


ドキュメント画面をConfigクラスで何か操作する場合、ContextViewをRobotlegsから注入する必要があります。

[Inject]
public var contextView:ContextView;

configureメソッド

configureメソッドでDIコンテナ化するクラスを登録します。


シングルトン登録は以下の書き方になります。

通常
injector.map(UserModel).asSingleton();
name指定
injector.map(UserModel, "modelName").asSingleton();

また、以下の方法でもシングルトンになります。

toValue
var user:UserModel = new UserModel();
injector.map(UserModel, "modelName").toValue(user);	

MediatorをViewに紐付けるには、以下の書き方になります。

mediatorMap.map(UserView).toMediator(UserViewMediator);

これでUserViewの対になるMediatorとして、UserViewMediatorがRobotlegsに登録されました。
※MediatorとViewは必ず1対1になる仕様です。


Commondを実行するイベントの登録は、以下の書き方になります。

commandMap.map(UserChangeEvent.USER_CHANGE).toCommand(UserCommand);

これでMediatorでUserChangeEvent.USER_CHANGEが呼ばれた場合、UserCommandクラスのメソッドが呼ばれるようになりました。


Mediator

UserViewMediator.as
	/**
	 * ユーザー画面のメディエータクラス
	 * UserModelとUserViewの仲介を行う
	 * 「ユーザの名前が変更された」というきっかけで「ビューにその名前を反映する」タスクを実行するだけのクラス
	 * 
	 * @author ogino
	 */
	public class UserViewMediator extends Mediator
	{
		
		//-----------------------------------------------------
		//コンポーネント
		//-----------------------------------------------------			
		
		[Inject]
		/** ユーザ画面 */
		public var view:UserView;
		
		//-----------------------------------------------------
		//プロパティ
		//-----------------------------------------------------			
		
		[Inject(name="modelName")]
		/** ユーザモデル */
		public var user:UserModel;
		
		//-----------------------------------------------------
		//オーバーライドしたメソッド
		//-----------------------------------------------------			
		
		/**
		 * @inheritDoc
		 */
		public override function initialize():void
		{
			// 名前が変更されたときに呼び出すメソッドをセット
			user.addEventListener(Event.CHANGE, changeView);
			view.addEventListener(UserChangeEvent.USER_CHANGE, view_userChange);
		}
		
		/**
		 * @inheritDoc
		 */
		public override function destroy():void
		{
			// 登録したメソッドを削除
			user.removeEventListener(Event.CHANGE, changeView);
		}

		//-----------------------------------------------------
		//イベントハンドラー
		//-----------------------------------------------------			
		
		/**
		 * 画面更新
		 * 
		 * @param e Event
		 */
		public function changeView(e:Event):void
		{
			view.nameChange(user.name);
		}
		
		/**
		 * 画面変更通知イベントハンドラー
		 * 
		 * @param	e
		 */
		private function view_userChange(e:UserChangeEvent):void 
		{
			// イベントをクローンする
			var newEvent:UserChangeEvent = UserChangeEvent(e.clone());
			// フレームワークに通知 このイベントに紐付けられたCommandクラスが呼ばれる
			eventDispatcher.dispatchEvent(newEvent);
		}		
	}

Mediatorは必ずrobotlegs.bender.bundles.mvcs.Medatorクラスを継承する必要があります。

public class UserViewMediator extends Mediator

Mediatorに紐付けられたView(この場合だとUserView)はMediator内でInjectタグで注入されます。

[Inject]
public var view:UserView;

Configクラスでシングルトン登録されたクラス(この場合はUserModelクラス)がある場合、Robotlegs側から注入されます

[Inject]
public var user:UserModel;

nameを指定すると、Configクラスでnameを指定することでRobotlegsから注入されます。
nameが違う場合、nameが無指定の場合は注入されません。

[Inject(name="modelName")]
public var user:UserModel;

MediatorクラスのeventDispatcherに、Configクラスで登録したイベントクラスをdispatchEventに渡すことで、Commandクラスを実行できます。

eventDispatcher.dispatchEvent(new UserChangeEvent(UserChangeEvent.USER_CHANGE));

※子画面からUserChangeEvent.USER_CHANGEをdispatchEventしてもCommandクラスは実行されないので注意


###オーバーライドしたメソッドの説明


1.initializeメソッド
 Mediatorに紐付けられたViewがstageにaddChildされたタイミングでRobotlegs側から呼び出されます。


2.destroyメソッド
 Mediatorに紐付けられたViewがstageにremoveChildされたタイミングでRobotlegs側から呼び出されます。


Command

UserCommand.as
	/**
	 * ユーザーに関するコマンド実行
	 * このクラスはコンフィグで設定したイベントがメディエーターで呼ばれた場合、executeメソッドがフレームワーク側から実行される
	 * 他のクラスから、コマンドを直接実行させるのは控えること
	 * 
	 * @author ogino
	 */
	public class UserCommand extends Command
	{
		
		//-----------------------------------------------------
		//プロパティ
		//-----------------------------------------------------			
		
		[Inject]
		/** イベント コマンドを実行したいイベントクラスをpublicで必ず記載すること */
		public var event:UserChangeEvent;		
		
		[Inject(name="modelName")]
		/** ユーザモデル */
		public var user:UserModel;		
		
		[Inject]
		/** コンテキストビュー */
		public var contextView:ContextView;		
		
		//-----------------------------------------------------
		//オーバーライドしたメソッド
		//-----------------------------------------------------			
		
		/**
		 * @inheritDoc
		 */
		override public function execute():void 
		{
			var view:UserView = new UserView();
			
			view.y = 20;
			user.name = "変更しました";
			// 画面を追加表示 コマンドクラスで画面遷移を実施するのがよさそう
			contextView.view.addChild(view);
		}
		
	}

RobotlegsにおいてCommandクラスはControllerです。

注意

Commandクラスは使い捨てです。
Commandに紐付けられたイベントクラスがMediatorから呼ばれるたびに、Robotlegs内でnewされています。


Commandは必ずrobotlegs.bender.bundles.mvcs.Commandクラスを継承する必要があります。

public class UserCommand extends Command

Commandクラスでは、Configクラスで紐付けられたイベントクラス(この場合はUserChangeEventクラス)をInjectタグで指定すると、Robotlegs側から注入されます。

[Inject]
public var event:UserChangeEvent;

MVCSの場合、CommandクラスからServiceを呼び出します。


[Inject]
public var service:SocketService;
				
override public function execute():void 
{		
   service.send();
}


###オーバーライドしたメソッドの説明


1.executeメソッド

 Commandに紐付けられたイベントクラスがMediator.eventDispatcher.dispatchEventを実行することで、Robotlegs側から呼び出されます。
 必ずoverrideしてください!


Model、View、Event

Model、View、Eventは通常通りの実装です。

UserModel.as
	/**
	 * ユーザー名のモデルクラス
	 * 
	 * @author ogino
	 */
	public class UserModel extends EventDispatcher
	{
		
		//-----------------------------------------------------
		//プロパティ
		//-----------------------------------------------------		
		
		//---------------
		//name
		//---------------	
		
		/**
		 * @private
		 */
		private var _name:String;
		
		/**
		 * ユーザー名
		 */
		public function get name():String { return _name; }
		
		/**
		 * @private
		 */
		public function set name(value:String):void 
		{
			_name = value;
			// 変更を通知
			dispatchEvent(new Event(Event.CHANGE));
		}
	}
UserView.as
	/**
	 * ユーザー情報表示画面
	 * 
	 * @author ogino
	 */
	public class UserView extends Sprite 
	{
		
		//-----------------------------------------------------
		//コンポーネント
		//-----------------------------------------------------			
		
		/** ユーザー名表示領域 */
		private var nameTextField:TextField;
		
		//-----------------------------------------------------
		//コンストラクタ
		//-----------------------------------------------------			
		
		/**
		 * コンストラクタ
		 */
		public function UserView() 
		{
			super();
			
			nameTextField = new TextField();
			nameTextField.addEventListener(MouseEvent.CLICK, nameTextFieldClickHandler);
			addChild(nameTextField);
		}
		
		//-----------------------------------------------------
		//メソッド
		//-----------------------------------------------------			
		
		/**
		 * 名前変更
		 * 
		 * @param	name
		 */
		public function nameChange(name:String):void 
		{
			nameTextField.text = name;
		}
		
		//-----------------------------------------------------
		//イベントハンドラー
		//-----------------------------------------------------			
		
		/**
		 * 名前テキストをクリックしたときのイベントハンドラー
		 * 
		 * @param	e
		 */
		private function nameTextFieldClickHandler(e:MouseEvent):void 
		{
			var e:MouseEvent = new MouseEvent(MouseEvent.CLICK);
			dispatchEvent(e);
			
			// メディエーターに更新イベントを通知
			dispatchEvent(new UserChangeEvent(UserChangeEvent.USER_CHANGE));
		}
UserChangeEvent.as
	/**
	 * ユーザーがデーターを変更した時のイベントハンドラー
	 * 
	 * @author ogino
	 */
	public class UserChangeEvent extends Event 
	{
		
		//-----------------------------------------------------
		//イベント定数
		//-----------------------------------------------------			
		
		/** ユーザー変更 */
		public static const USER_CHANGE:String = "userChange";
		
		//-----------------------------------------------------
		//コンストラクタ
		//-----------------------------------------------------			
		
		/**
		 * コンストラクタ
		 * 
		 * @param	type
		 * @param	bubbles
		 * @param	cancelable
		 */
		public function UserChangeEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false) 
		{ 
			super(type, bubbles, cancelable);
		} 
		
		//-----------------------------------------------------
		//オーバーライドしたメソッド
		//-----------------------------------------------------			
		
		/**
		 * @inheritDoc
		 */
		override public function clone():Event 
		{
			var e:UserChangeEvent = new UserChangeEvent(type, bubbles, cancelable);
			return e;
		}
		
	}

以上、Robotlegs2 の実装したサンプルコードの説明になります。

5
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?