Nach der Einführung in das Robotlegs ActionScript-Framework gibt es nun ein weiteres Robotlegs-Beispiel. Schwerpunkt der Erklärung liegt auf den „Services” der MVCS-Referenzimplentierung von Robotlegs.
Was sind Services? Services sind zuständig, eine Anwendung mit Daten von externen Quellen zu versorgen. Dies kann z.B. die Anfragen an Datenbanken, das Filesystem, Webservices oder Webseiten-APIs sein. Die externe Anbindung wird also in eine Serviceklasse gekapselt.
Services encapsulate this interaction with external entities, and manage the results, faults, and other events that result from this interaction.
Als Beispiel für einen Service verwende ich die Twitter-Suche, die den aktuellste Tweet mit dem Hashtag #Flash zurückliefert (siehe Tweetr — Twitter-API für Flash).
Robotlegs und Flex Framework
Übrigens: Ich habe dieses Mal das Flex-Framework verwendet. Es wird deutlich, wie sich der Robotlegs-Aufbau eines reinen ActionScript-Projekts (siehe voriger Artikel) ebenso mit einem Flex-Projekt durchführen lässt.
Der einziger wesentliche Unterschied besteht bei meinem Beispiel darin, dass die Hauptdatei (main.mxml) den Context
mithilfe von MXML aufruft und die MXML-basierte Viewkomponente (TweetBox
) auf der Bühne platziert.
[xml]
[/xml]
Beispiel anschauen
[kml_flashembed publishmethod=“dynamic“ fversion=“10.0.0″ movie=“/wp-content/uploads/2009/12/robotlegs/Main1.swf“ width=“500″ height=“300″ targetclass=“flashmovie“]
[/kml_flashembed]
Ablauf
Im Folgenden eine kurze Beschreibung der Abläufe, wenn der Service benutzt wird.
Buttonklick führt Command aus
Beim Klick auf den loadButton
in der View wird von der Mediator-Klasse ein Event ausgelöst.
[as]
dispatch(new FlowEvent(FlowEvent.LOAD_LATEST_TWEET))
[/as]
Mapping des Events im Context
Die Zuordnung für dieses Event zum entsprechenden Command
mit dem Namen LoadLatestTweet
erfolgt im Context
. Als Folge wird deshalb LoadLatestTweet
ausgeführt.
[as]
commandMap.mapEvent(FlowEvent.LOAD_LATEST_TWEET, LoadLatestTweet);
[/as]
Command ruft Service auf
Die Klasse LoadLatestTweet
ruft den Twitter-Service auf, den es injiziert bekommt (mehr zum Inject
weiter unten).
[as]
public class LoadLatestTweet extends Command {
[Inject]
public var service:ITwitterService;
public function LoadLatestTweet() {
}
override public function execute():void {
service.getLatestTweet();
}
[/as]
Service liefert Resultat als Event
Der Service sucht nach dem aktuellsten Tweet und liefert das Ergebnis als Payload eines Events.
[as]
var evt:SingleTweetEvent = new SingleTweetEvent(SingleTweetEvent.RESULT);
evt.text = tweet.text;
evt.tweetAge = TweetUtil.returnTweetAge(tweet.createdAt);
evt.userProfileImage = tweet.userProfileImage;
dispatch(evt);
[/as]
Service
Für den Beispiel-Twitter-Service gibt es ein einfaches Interface, ITwitterService
. Dieses definiert, dass es die Methode getLatestTweet
geben muss.
[as]
public interface ITwitterService {
function getLatestTweet():void;
}
[/as]
Im Beispiel habe ich zwei Klassen, die dieses Interface implementieren: TwitterMockupService
und TwitterSearchService
. Die erste ist gar kein echter Service, sondern liefert nur Testdaten. Die zweite Klasse nutzt Tweetr und führt eine echte Abfrage durch.
Das Praktische ist nun, dass man bei der Erstellung des Service-Objekts im Context
problemlos den tatsächlichen Service wechseln kann (da beide das gleiche Interface implementieren). Auch ein zukünftiger Austausch des Service ist kein Problem, z.B. könnte man auch stattdessen den Twitter-XML-Feed auslesen. Somit hat man eine saubere Trennung des Services vom restlichen Code.
[as]
// Singleton für den Service erstellen
injector.mapSingletonOf(ITwitterService, TwitterSearchService);
// Für Mockup-/Dummycontent stattdessen diese Zeile hier verwenden:
//injector.mapSingletonOf(ITwitterService, TwitterMockupService);
[/as]
Hier das Beispiel mit dem „gefakten” Service.
[kml_flashembed publishmethod=“dynamic“ fversion=“10.0.0″ movie=“/wp-content/uploads/2009/12/robotlegs/Main2.swf“ base=“.“ width=“500″ height=“300″ targetclass=“flashmovie“]
[/kml_flashembed]
Wer noch Ergänzungen oder Fragen hat, einfach einen Kommentar hinterlassen.
Download: Quelldateien (.zip)
[ad]
ich weiß, dass das beispiel schon etwas älter ist, aber ich bin optimistisch, dass mir doch jemand eine frage beantworten kann:
angenommen man möchte in dem beispiel mehrere TweetBoxen verwenden, die aber jeweils andere ITwitterService Implementation haben sollen. Wie kann ich differenzieren, welches View-Element mit welchem Command gemappt wird?
Übrigens, super Tutorial, war sehr verständlich aufbereitet – danke!
Danke.
Das sollte so gehen:
injector.mapSingletonOf( ITwitterService, TwitterSearchService, 'name1' );
injector.mapSingletonOf( ITwitterService, TwitterMockupService, 'name2' );
Du erstellt also zwei Services. Auf die gleiche Weise könntest du auch 2 Models erstellen.
Beim Inject greift du dann auf den jeweils gewünschten über den Namen zu:
[Inject name="name1"]
public var …
Folgendes klappt bei mir nicht:
[Inject name="name1"]
public var service:IFileManagerService;
Da bekomme ich einen syntax error ?