Chapter 5. The Robotlegs context in action

Every Robotlegs project begins with a context. Until the context is instantiated, Robotlegs isn’t up and running. To get your Robotlegs application going, you have to do two things: provide the context with a contextView and ask it to run startup.

Provide the context with a root-view

Every Robotlegs application requires a root-view—an instance of DisplayObjectContainer—which is the view that will be provided to the mediatorMap, so that when child views are added to this root-view they can be automatically mediated (an instance of their mediator is created and provided with the child view that it mediates for).

Tip

If your application is non-visual then just provide any-old placeholder instance of Sprite or DisplayObjectContainer.

Example 5-1. MosaicTool: mosaicTool.as In AS3/Flash, you’ll provide this view as the first parameter of the constructor
public class mosaictool extends Sprite
{

     protected var _context:MosaicContext;

     public function mosaictool()
     {
         _context = new MosaicContext(this);
     }
  ...
Example 5-2. KanbanApp: PersonalKanban.mxml In Flex the context can be initialized with an MXML tag; not having access to the constructor, you’ll provide this view using the contextView property
<WindowedApplication xmlns:fx="http://ns.adobe.com/mxml/2009"
                     xmlns="library://ns.adobe.com/flex/spark"
                     xmlns:kanban="robotlegs.examples.kanban.*"
                     xmlns:view="robotlegs.examples.kanban.view.*"
                     showStatusBar="false">

    <fx:Style source="css/style.css"/>

    <fx:Declarations>
        <kanban:PersonalKanbanContext contextView="{this}"/>
    </fx:Declarations>

Ask it to run startup()—immediately or when you’re ready

In most situations you’ll want to start your application as soon as possible—in AS3 this means right from the constructor, and in Flex this means as soon as the contextView has been set. This is the default, but in particular cases where you need to do something else before your context gets to work configuring and firing up your app, you can set autoStartup to false and run startup() manually.

Use startup() to provide your injection rules, map your mediators to views and commands to events

startup() is the most important method in your whole app. It’s where you initially configure your application—where you determine which classes will be injected and how, which view classes will get what kind of mediators, and what commands will be triggered by events.

Example 5-3. KanbanApp: PersonalKanbanContext.as All of your application’s configuration can be contained in the Context
override public function startup():void
{
  mediatorMap.mapView(StatusGroup, StatusGroupMediator);
  mediatorMap.mapView(TaskLane, TaskLaneMediator);
  mediatorMap.mapView(TaskEntryBar, TaskEntryBarMediator);

  injector.mapSingletonOf(IStatusService, SQLStatusService);
  injector.mapSingletonOf(ITaskService, SQLTaskService);

  injector.mapSingleton(StatusListModel);
  injector.mapSingleton(TaskListModel);

  commandMap.mapEvent(UpdateTaskWithStatusEvent.UPDATE, UpdateTaskWithStatusCommand);
  commandMap.mapEvent(SaveTaskEvent.SAVE, SaveTaskCommand);
  commandMap.mapEvent(ConfigureDatabaseEvent.CONFIGURE, ConfigureDatabaseCommand);
  commandMap.mapEvent(DatabaseReadyEvent.READY, LoadStatusesCommand);
  commandMap.mapEvent(StatusesLoadedEvent.LOADED, LoadTasksCommand);
  commandMap.mapEvent(DeleteTaskEvent.DELETE, DeleteTaskCommand);
  commandMap.mapEvent(DatabaseErrorHandlerEvent.ERROR, DatabaseErrorHandlerCommand);

  dispatchEvent(new ConfigureDatabaseEvent())
}

You will quickly find that this approach leads to a rather messy startup() method in an app of any significant size. In fact, the Personal Kanban example above is right on the threshold of being much too large. A solution to this is to break the configuration down into manageable chunks. The Mosaic application provides an example of doing that with configuration helper classes.

Example 5-4. MosaicTool: MosaicContext.as Breaking down configuration into small coherent helper classes
override public function startup():void
{
  new BootstrapConfigValues(injector);
  new BootstrapModels(injector);
  new BootstrapServices(injector);
  new BootstrapCommands(commandMap);
  new BootstrapTileSupplyCommands(commandMap);
  new BootstrapClasses(injector);
  new BootstrapViewMediators(mediatorMap);

  addRootView();
  super.startup();
}
Example 5-5. MosaicTool: BootstrapConfigValues.as Each bootstrap class is responsible for configuring a specific set of injections or mappings
public class BootstrapConfigValues
{
public function BootstrapConfigValues(injector:IInjector)
{
    injector.mapValue(ConfigName, new ConfigName("MosaicDesignerConfig"));
    injector.mapValue(DefaultDesignName, new DefaultDesignName("Practice Design"));
    injector.mapValue(DefaultGridSize, new DefaultGridSize(15, 20));
    injector.mapValue(DefaultTileColor, new DefaultTileColor(0x333333));
    injector.mapValue(DefaultWorkspaceColor, new DefaultWorkspaceColor(0x000000));
}
}

As your project grows you will appreciate the readability this separation of configuration concerns brings.

Shutting down a Context

In most situations you won’t need to shutdown a context, but if, for example, your Robotlegs application is a game loaded into another swf, you might find it useful to be able to kill your Robotlegs context and create it again fresh when the game is restarted.

In most cases, getting rid of a context is as simple as nulling the variable where you created a reference to the context. The garbage collector will then handle all the clean up.

The Context class has a shutdown() method, which you can override if you need to do any clean up specific to your application. This should only be necessary if you’ve created references between your context and an object outside of it, usually in a loading shell.

If you do need to do some specific clean up, calling super.shutdown() at the end of your shutdown() method will dispatch a ContextEvent.SHUTDOWN_COMPLETE event, which you can listen for before nulling the reference to the context.

Now you have some Context

You can think of the Context as a container for the injections you specify on the injector. Within a specific Context, a set of objects are created and injected based on the configuration values setup for that Context. As well as objects and injection rules, the context contains rules about how to map views to mediators, and how to map events to commands, via the heart of your controller layer: the CommandMap.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.220.16.184