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
.
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).
If your application is non-visual then just provide any-old
placeholder instance of Sprite
or DisplayObjectContainer
.
public class mosaictool extends Sprite { protected var _context:MosaicContext; public function mosaictool() { _context = new MosaicContext(this); } ...
<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>
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.
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.
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.
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(); }
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.
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.
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
.
18.220.16.184