Robotlegs for Mobile Apps and Games

Today we set up a simple App using the Robotlegs Framework.

Description:
This is a brief tutorial that will show you how to setup Robotlegs and how to move data around the framework. Robotlegs is an AS3 framework that relies heavily on dependency Injection. It removes the need of event bubbling through your application and instead uses a shared event dispatcher.

Additionally it removes the need to pass objects around and creating false dependencies. If you are familiar with a MVC or MVCS design pattern then you will be familiar with some of the structure of Robotlegs, but the big difference is the Context. I’m not going to get really dwell too deeply into how Robotlegs Dependency Injection works because there is plenty of great literature out there for it already, instead we will focus on how to use the Context, Mediators, Events and Commands.

The Actionscript Developer’s Guide to Robotlegs (Hooks & Fallow) is a great book from O’Reilly that I recommend reading.

Prerequisites :
Flash Builder 4.6 profiency.
robotlegs-framework-v1.5.2 SWC

Level:
Intermediate

Follow along or download the completed example

The object of this tutorial will be a basic set up of a robotlogs project in Flash Builder 4.6 and to move a simple string through the framework. To do this we will create a view with a button and attach a mediator in order to send a user generated event. We will create a model and store information about what was pressed and finally we’ll send something back to the view to let us know that the data was changed. While doing this we’ll discuss views, mediators, the context and commands.

Lets get started making this project…

Creating a Project
1. Right Click in the Package Explorer and create new Flex Mobile Project
2. Enter the Project name (RobotlegsTutorial), choose default location, choose AIR for desktop and radio button the correct SDK (in my case 4.6). Click next.
3. Server Settings can be left to default. Click Next
4. In the Build Paths window we need to add the Robotlegs SWC. This can be found in the bin folder of the framework you downloaded earlier (link under prerequisites). Click on ADD SWC find this file and hit OK. Then hit Finish.
5. Toggle down the src folder and the default package so you can see RobotLegsTutorial.mxml.

Setting up Folder Structure.
The first thing we want to do is set up some good folder structure because that is important when working with frameworks.
1. right click on the src folder and create a new folder, name it com and hit enter
2. right click on the com folder to create five folders. name them contexts, controllers, events, model & view.
3. right click on the view folder and create two folders. name them component and view.

Show Line Numbers
1. right click in the left margin of your source code and select Show Line Numbers.

Create Context
The context is the heart of the application. It is where you will bind your views to the mediators and where you create a singleton on your model and were you will put global listeners to events dispatched throughout the application. It takes two params, Display Object Container (which will be the root of your application) and a Boolean for autostartup.

In Flex the display object container will be apps main mxml, or RobotlegsTutorial.mxml file. We will pass that parameter in the fx:Declarations namespace. of the RobotlegsTutorial.mxml.

1. right click on the contexts folder and select New Actionscript Class.
2. For name put ApplicationContext
3. For Superclass type Context and your code hinting should kick in and give you org.robotlegs.mvcs.Context*. Hit Finish.

Note: If you don’t get code hinting then you don’t have the library swc correctly installed. Check your libs.

We can move on, but we need to remember to pass the RobotlegsTutorial.mxml into the context as a display object later.

Create Model
1. right click on the model folder and create a new Actionscript Class.
2. Under name call it Application Model, under superclass type in Actor. Code help will get you to org.robotlegs.mvcs.Actor. Actor is the super class for models.
3. Hit Finish

Create the Models Interface
1. right click on the model folder and create a new Actionscript Interface
2. name it IModel
3. Click Finish

Create Views

StageView.
I like to create a view that holds all my views in my app. Sort of a container. I call it StageView and I use it every time I make an app . It sole purpose is to add or remove views from the display. You wouldn’t want to add views to your main display object but rather add a container (in this case StageView) to the main mxml file (in this case (RobotlegsTutorial.mxml). This file will do very little besides provide a container.

1. right click on the components folder and create a new MXML Component.
2. fill out the name field and call it StageView

Instead the Mediator that will be bound to this view will do the bulk of the work.

StageViewMediator
In Robotlegs, the important views get Mediators. Mediators are layers above a view that act as liaisons to the application. Their role is to pass User Input to the context or model and to receive data from the Model to display in the view. Robotlegs is very flexible you could listen for an event from the Context and call a command to change something in your view, or you can Inject the model into your Mediator so that you can just update the view by using getters in your model.

For the StageViewMediator I like to use the eventMap to mapListener and globally listen for events happening around the application. When these events are received we fire an event to change the view in the StageView.

1. right click on the mediator folder and select New ActionScriptClass.
2. Name it StageViewMediator
3. under superclass choose Mediator
4. Hit Finish.

StartView
1. right click on the components folder and create a new MXML Component
2. fill out the name field and call it StartView

StartViewMediator
1. right click on the mediator folder and select New ActionScript Class
2. Name it StartViewMediator
3. under superclass select Mediator.

Pass a DisplayObjectContainer into the Context
In order for Robotlegs to work we need to pass a Display Object Container into the context and then use the Context’s startup function to bind views, inject singletons of our modes and map Event commands. Ok lets get started.

1. In the RobotlegsTutorial.mxml file, (we need to import our components and our context) insert the name space contexts and the namespace component using xmlns as show below:

  1. xmlns:contexts="com.contexts.*" xmlns:component="com.views.component.*"

2. In we need to add the mxml file as our display object container like so…

  1.  <fx:Declarations>
  2.   <!– Place non-visual elements (e.g., services, value objects) here –>
  3.   <contexts:ApplicationContext contextView="{this}"/>
  4.  </fx:Declarations>

3. finally we need to add the StageView as a component of the DisplayObjectContainer so it is automatically displayed when we start the app.

  1.  <component:StageView/>

Set Up the Context
Go back to your ApplicationContext.as file

1. Import all your models views and mediators

  1.  import com.model.ApplicationModel;
  2.  import com.model.IModel;
  3.  import com.views.component.StartView;
  4.  import com.views.component.StageView;
  5.  import com.views.mediator.StartViewMediator;
  6.  import com.views.mediator.StageViewMediator;

2. Under the constructor function we’re going to override public function startup().

  1.  override public function startup():void {
  2.    // couple views
  3.    mediatorMap.mapView(StageView, StageViewMediator);
  4.    mediatorMap.mapView(StartView, StartViewMediator);
  5.    
  6.    //map singleton model
  7.    injector.mapSingletonOf(IModel, ApplicationModel)
  8.    injector.mapSingleton(ApplicationModel)
  9.    
  10.    // Map commands
  11.    commandMap.mapEvent(StartEvent.START_UP, GetStartUpDataCommand, StartEvent);
  12.    
  13.    // add StageView to Main Container
  14.    // This is done in the RobotLegsSetup.mxml
  15.    
  16.    super.startup();
  17.    
  18.   }

The Startup function of the Context is where we will use the heavy hitting methods of the framework. This is where we determine what gets injected. mediatorMap.mapview is for coupling views and mediators, mapSingleton(Model) to request the same instance of the model for each request, mapSingletonOf(IModel, Model) where interface requests are met by the same instance of the model. Finally commandMap.mapEvent to call Commands when certain events are fired throughout the application.

Line 30: We use the mediatorMap to map the views to one another. In this case, StageView is coupled to StageViewMediator. We will still need to inject the StageView into the StageViewMediator
Line 31: We repeat for the StartView and StartView Mediator
Line 34: We will use the injector.mapSingletonOf to map our IModel interface to our Application Model.
Line 35: We use the injector.mapSingleton to create a single instance of the Application Model
Line 38: We use the commandMap.mapEvent to listen for an event to fire a command. In this case we’ll need to create a StartEvent and a GetStartUpDataCommand when its fired.
Line 43: We super the startup() function of the Context.

3. Lets comment out the commandMap.mapEvent line for now since we’re not quite ready to create events and commands.

Populate our View with UI components
Go back to your StartView.mxml and lets add a button and a text field.

1. Create a spark group under the fx declarations and inside place a spark VGroup

  1.            <s:Group>
  2.   <s:VGroup  x="200" y="100">
  3.   </s:VGroup>
  4.  </s:Group>

2. Inside the VGroup place a Spark component RichText field with the ID simpleTextField and default text “default text” as seen below

  1.            <s:Group>
  2.   <s:VGroup  x="200" y="100">
  3.    <s:RichText id="simpleTextField" text="Press Play"/>
  4.    <s:Button id="startBtn" label="Start Game" visible="true"/>
  5.   </s:VGroup>
  6.  </s:Group>

To summarize, we have added a rich text field to the view and made the default text be “Press Play” and we have given the text field an ID of “simpleTextField”. Additionally we have added a start Button. The idea is to remove the start button and change the text when the user pushes the button.

Create a Mediator for the View
1. go to the StartViewMediator
2. We wont be using the constructor, but you can leave it.
3. Lets import our StartView into the mediator

  1.            import com.views.component.StartView;

4. Above the constructor, we’re going to Inject our View into the Mediator as shown below. When speaking this view in the Mediator, we will use this variable.

  1.             [Inject]
  2.  public var startView:StartView;

5. Mediators kick off by overriding a public function called onRegister. It is here where we will put our listeners and such. so lets write that function now

  1.          override public function onRegister():void {
  2.    // set up listener for upcoming events
  3.    
  4.   }

6. use the eventMap to map a listener to the eventDispatcher to listen for a custom event called StartEvent (We still need to create it) that will be called from the ApplicationModel

  1.          override public function onRegister():void {
  2.    // set up listener for upcoming events
  3.               eventMap.mapListener(eventDispatcher, StartEvent.MODEL_MESSAGE_TO_VIEW, onReceiptOfMessage, StartEvent, false, 0, true);
  4.    
  5.   }

7. Add an EventListener to the button in the view

  1.          override public function onRegister():void {
  2.    // set up listener for upcoming events
  3.               eventMap.mapListener(eventDispatcher, StartEvent.MODEL_MESSAGE_TO_VIEW, onReceiptOfMessage, StartEvent, false, 0, true);
  4.    // add event listener for startButton
  5.    startView.startBtn.addEventListener(MouseEvent.CLICK, onStartClick, false, 0, true);
  6.    
  7.   }

8. Import Mouse Events

  1.          import flash.events.MouseEvent;

9. Write the function that is called when the button is clicked, called onStartClick

  1.          private function onStartClick(e:MouseEvent):void {
  2.    // dispatch event
  3.    dispatch(new StartEvent(StartEvent.START_UP, false,false, "Game Started!"));
  4.    //hide button
  5.    startView.startBtn.visible = false;
  6.   }

Line 42: Dispatch a custom event with a message as a parameter which is a String “Game Started!”. We’re going to pass this to the model through a command.
Line 34: Hide the button.

10. Write the function that is called when the Model sends an Event back

  1.          private function onReceiptOfMessage(e:StartEvent):void {
  2.    trace("startViewMediator  = " + e.message)
  3.    //populate text field from model
  4.    startView.simpleTextField.text = e.message;
  5.    
  6.   }

Line 35: When the model sends a Custom Start event called MODEL_MESSAGE_TO_VIEW we fire this function. In the event is a message. We populate the text field in the view with the message.

There is still a lot to do. We need to create the custom event and we need to create a command. We also will need to revisit our Context and have the Command talk to the interface for the Model and finally the model needs to send a message to our StartViewMediator.

Events
Events are used in robotlegs to pass data back and forth and to alert components that something has happened.

Create Custom Event
1. on the events folder, right click select New ActionScript Class
2. Name it StartEvent
3. Update the class to match the sample below

StartEvent.as

  1.           package com.events
  2. {
  3.  import flash.events.Event;
  4.  
  5.  public class StartEvent extends Event
  6.  {
  7.  
  8.   static public const START_UP:String = "START_UP";
  9.   static public const MODEL_MESSAGE_TO_VIEW:String = "MODEL_MESSAGE_TO_VIEW"
  10.  
  11.   public var message:String;
  12.  
  13.   public function StartEvent(type:String, bubbles:Boolean=false, cancelable:Boolean=false, message:String = "")
  14.   {
  15.    trace("StartEvent Constructor")
  16.    this.message = message;
  17.    super(type, bubbles, cancelable);
  18.   }
  19.  
  20.   override public function clone():Event {
  21.    return new StartEvent(type, bubbles, cancelable, message);
  22.   }
  23.  }
  24. }

Line 3: import flash.events.Event
Line 8: Create two static public constant Events. One to be dispatched from the StartViewMediator when the startBtn is pushed. The other to be dispatched by the Model when a command is fired.
Line 13: Add a third parameter to the constructor that is a string. This was passed from the StartViewMediator when the button was pushed.
Line 16: Pass it to the public var message

Create Command
1. Right click on the controllers folder and select New ActionScript Class
2. Name the Class GetStartUpDataCommand
3. For superclass type in Command.

Command.as

  1.         package com.controllers
  2. {
  3.  
  4.  import com.model.IModel;
  5.  
  6.  import org.robotlegs.mvcs.Command;
  7.  
  8.  import com.events.StartEvent
  9.  
  10.  
  11.  public class GetStartUpDataCommand extends Command
  12.  {
  13.  
  14.   [Inject]
  15.   public var applicationModel:IModel;
  16.  
  17.   [Inject]
  18.   public var startEvent:StartEvent;
  19.  
  20.   override public function execute():void {
  21.    applicationModel.sendDataToTextView(startEvent.message)
  22.   }
  23.  }
  24. }

Line 4:Import the IModel interface
Line 6: Import the Command
Line 8:Import the StartEvent
Line 14:Inject the model’s Interface
Line15:Inject the custom Event
Line 21: request the Model to fire a function and pass it the string from our custom event.

Finalize the Context
1. In the ApplicationContext.as file uncomment the line wihtemapEvent that has a command firing off when the custom Event is received.

  1.             commandMap.mapEvent(StartEvent.START_UP, GetStartUpDataCommand, StartEvent);

2. Import the Custom Event and the Command

  1.             import com.controllers.GetStartUpDataCommand;
  2.  import com.events.StartEvent;

Now that we have our custom Event and our Command we can listen for the Event in the Context using the commandMap.mapEvent and then fire a command when that particular event is called.

Our ApplicationContext.as file should now look like this.

  1.             package com.contexts
  2. {
  3.  import com.controllers.GetStartUpDataCommand;
  4.  import com.events.StartEvent;
  5.  import com.model.ApplicationModel;
  6.  import com.model.IModel;
  7.  import com.views.component.StartView;
  8.  import com.views.component.StageView;
  9.  import com.views.mediator.StartViewMediator;
  10.  import com.views.mediator.StageViewMediator;
  11.  
  12.  import flash.display.DisplayObjectContainer;
  13.  import flash.events.Event;
  14.  
  15.  import mx.controls.Text;
  16.  
  17.  import org.robotlegs.base.ContextEvent;
  18.  import org.robotlegs.mvcs.Context;
  19.  
  20.  
  21.  public class ApplicationContext extends Context
  22.  {
  23.   public function ApplicationContext(contextView:DisplayObjectContainer=null, autoStartup:Boolean=true)
  24.   {
  25.    super(contextView, autoStartup);
  26.   }
  27.  
  28.   override public function startup():void {
  29.    // couple views
  30.    mediatorMap.mapView(StageView, StageViewMediator);
  31.    mediatorMap.mapView(StartView, StartViewMediator);
  32.    
  33.    //map singleton model
  34.    injector.mapSingletonOf(IModel, ApplicationModel)
  35.    injector.mapSingleton(ApplicationModel)
  36.    
  37.    // Map commands
  38.    commandMap.mapEvent(StartEvent.START_UP, GetStartUpDataCommand, StartEvent);
  39.    
  40.    // add StageView to Main Container
  41.    // This is done in the RobotLegsSetup.mxml
  42.    
  43.    super.startup();
  44.    
  45.   }
  46.  }
  47. }









Once everything is created now in the correct folder structure and your Package Explorer should like like Fig 1 Left.
















All your classes are done with the exception of the Model and its Interface

Complete the Models Interface
1. Return to the IModel.as file.
2. Create a function to call send data to the text view and pass it the string from the Event.

The IModel.as file should like like this.

  1.             /package com.model
  2. {
  3.  public interface IModel
  4.  {
  5.   function sendDataToTextView(s:String):void;
  6.  }
  7. }

Complete the Model

ApplicationModel.as Complete

  1.        package com.model
  2. {
  3.  import com.events.StartEvent;
  4.  import com.model.IModel;
  5.  
  6.  import org.robotlegs.mvcs.Actor;
  7.  
  8.  public class ApplicationModel extends Actor implements IModel
  9.  {
  10.  
  11.   private var message:String;
  12.  
  13.   public function ApplicationModel()
  14.   {
  15.    //super();
  16.    message = "message";
  17.   }
  18.  
  19.   public function sendDataToTextView(s:String):void {
  20.     message = s;
  21.     //trace(message)
  22.     dispatch(new StartEvent(StartEvent.MODEL_MESSAGE_TO_VIEW, false,false, message));
  23.   }
  24.  }
  25. }

Fig 2 shows how the event flows from the Button in the view to the View’s Mediator to the Context. The Context listens for that Event and fires a Command. The Command has the Event and the Models Interface injected so it can get the data passed from the event into a function in the Model. Finally the model dispatches an event with updated data to the StartViewMediator (thanks to the mapListener method of the eventMap class) and when the Mediator receives the event, it calls a method to change the Text Field in the View.

There you have an example of round trip of data in Robotlegs. Hopefully this is somewhat helpful in getting you started with Robotlegs using Flash Builder 4.6. I plan on going into case uses for Robotlegs in both apps and games.

Posted on March 24, 2012 at 7:44 pm by Runtime · Permalink
In: Flash Builder, Flex, Tutorial · Tagged with: , ,

Leave a Reply

You must be logged in to post a comment.