-
Notifications
You must be signed in to change notification settings - Fork 2
5. Create views
The view are classes that will display your application graphic elements such as buttons, animations, user interface, and so on. Your views should be completely free of framework code. They must be written in a efficient decoupled way so your views can easily be changed and re-used.
Ideally, the logic of the view should be written in other classes (such as mediator), so the view stays as simple as possible. But that is a choice and not required at all.
Here is a simple view that displays a textfield, there should be nothing else than the graphic elements and some methods (the view API) to update its content.
package com.soma.core.demo.helloworld.views {
import flash.events.MouseEvent;
import com.soma.core.demo.helloworld.controller.events.MessageEvent;
import flash.text.TextField;
import flash.display.Sprite;
public class MessageView extends Sprite {
private var _textfield:TextField;
public function MessageView() {
_textfield = new TextField();
_textfield.text = "Click me!";
_textfield.addEventListener(MouseEvent.CLICK, clicked);
addChild(_textfield);
}
private function clicked(event:MouseEvent):void {
dispatchEvent(new MessageEvent(MessageEvent.REQUEST));
}
public function updateMessage(value:String):void {
_textfield.text = value;
}
}
}
There are two ways to register a view to the framework and this can be done in four places:
- in the framework instance
- in a wire instance
- in a mediator instance
- in a command instance
In either place, a view can be registered this way:
addView(NAME_VIEW, new MySprite());
The view instances registered to the framework can easily be retrieved in the same four places.
var view:MySprite = getView(NAME_VIEW) as MySprite;
A view class that is not used anymore can be removed in the same four places. When a view gets removed, the framework will automatically call a “probable” dispose
method and set to null in order to be garbage collected. Note that a view doesn’t have to implement a dispose
method, it is completely optional.
removeView(NAME_VIEW);
if (hasView(NAME_VIEW)) {
// do something
}
In wire instances, it is a good practice to create getter shortcuts. Here are some examples:
private function get myView():MySprite {
return MySprite(getView(NAME_VIEW));
}
They can now be used directly from another place:
override protected function initialize():void {
trace(myView.doUpdateSomething());
}
Injection makes it even easier to register and retrieve a view from different places. The mediators are classes especially built to manage a single view.
They are many ways to register a view to the framework using injection depending of the behavior wanted when it gets injected.
If only one instance of a view class must be created, the view can be registered using the injector.mapSingleton()
method. The name Singleton doesn’t mean that it is a real Singleton. It means that only one instance will be created when needed, making a good of lazy instantiation, and that the same instance will be injected every time it is asked.
injector.mapSingleton(MySprite);
This line means: every time I ask for a MySprite to be injected, create a new instance of the MySprite class if it is the first time I ask. Otherwise, inject the instance that has been already created.
An instance can be created before being injected, if needed, using the injector.getInstance()
method.
var view:MySprite = injector.getInstance(MySprite) as MySprite;
If a view requires to be a new instance every time it gets injected, the method injector.map()
can be used.
injector.map(MySprite, MySprite);
This line means: every time I ask for a MySprite class to be injected, create a new instance of the MySprite class.
A view can also be instantiated and register to the injector. Every time, the view class must be injected, this precise instance will be used for the injection.
var view:MySprite = new MySprite();
injector.mapToInstance(MySprite, view);
This line means: every time I ask for a MySprite class to be injected, use the view instance that has been registered.
A view class or instance can be unregistered (unmapped) from the injector using the injector.removeMapping()
method.
injector.removeMapping(MySprite);
See the section “Create a mediator” for more information on this specific ways to handle views.
As an overview, a view can be registered to the mediator manager.
mediators.mapView(MySprite, MySpriteMediator);
Everytime a MySprite instance will be instantiated and added to a display list, the framework will create a MySpriteMediator instance where the corresponding view can be managed.
To inject a viewinstance in another class, the injector will need to find a [Inject]
metadata tag in the injectee class.
To perform an injection, the injectee class must be created by the injector, or manually with the injector.injectInto()
method.
Here is a simple example of a view that get injected in a wire.
// mapping rule
injector.mapSingleton(MySprite);
// create a wire instance to inject the view into
injector.getInstance(WireExample);
// or
var wire:WireExample = new WireExample();
injector.injectInto(wire);
package {
import com.soma.core.wire.Wire;
import com.soma.core.interfaces.IWire;
public class WireExample extends Wire implements IWire {
[Inject]
public var view:MySprite;
override public function initialize():void {
// called when the wire has been registered to the framework
trace("view injected:", view);
}
override public function dispose():void {
// called when the wire has been removed from the framework
}
}
}
A view shouldn’t have any direct access or relation to the framework in order to be re-usable in another context or without the framework.