Parsley i Flex 4 w kilku krokach

Parsley jest frameworkiem aplikacji dla programów utworzonych w języku ActionScript 3.0. Działa jako kontener IoC, zapewnia także mechanizm komunikacji pozwalający na tworzenie architektury aplikacji zawierającej komponenty luźno ze sobą związane. Komponenty (obiekty) zarządzane przez framework mogą być konfigurowane za pomocą metadanych oraz języków MXML, XML i ActionScript. Cechą wyróżniającą Parsley’a jest jego niezależność od frameworku Flexa (czyli Flex SDK). Programiści Flasha oraz programujący w “czystym” ActionScript mogą także korzystać z Parsley’a.

Ale o co chodzi?

Celem tego artykułu jest zademonstrowanie filozofii frameworka Parsley. W kilku krokach utworzymy prostą aplikację Flexa z wykorzystaniem podstawowych mechanizmów tego frameworka. Jeżeli są Ci obce takie terminy jak Dependency Injection (DI) lub Inversion of Control (IoC), koniecznie zajrzyj do Dependency Injection (DI) oraz Inversion of Control (IoC) w ActionScript 3.

Uwaga! Zaczynamy.

W trakcie tworzenia aplikacji będę korzystał z Adobe Flash Builder 4.0.1 oraz Flex SDK 4.1.

Aby rozpocząć pracę z frameworkiem Parsley w projekcie Flexa, utwórz nowy projekt Flexa w Flash Builderze 4 (FB4). Z frameworka można też korzystać w Flex SDK 3, ale tutaj skupimy się na wersji 4.1.

Pobierz ze strony www.spicefactory.org plik ZIP zawierający pliki SWC frameworka. Rozpakuj plik ZIP (w moim przypadku jest to parsley-2.3.M3.zip) i przejdź do folderu “release”. Zwróć uwagę, że potrzebujemy tylko niektórych plików SWC z tego folderu. Ponieważ tworzymy aplikację za pomocą Flex SDK 4, będziemy potrzebowali parsley-flex4-2.3.M3.swc oraz spicelib-flex-2.3.M3.swc.

Przekopiuj pliki parsley-flex4-2.3.M3.swc oraz spicelib-flex-2.3.M3.swc do folderu “libs” w nowo utworzonym projekcie Flexa, dzięki temu uzyskamy dostęp do API frameworka z naszej aplikacji.

Aplikacja demonstracyjna będzie się składała z dwóch komponentów wizualnych (view), powiązanych z nimi modeli, pliku konfiguracyjnego Parsleya, pliku definiującego rodzaj przesyłanych danych oraz głównego pliku aplikacji. Jeśli chcesz, możesz od razu zobaczyć efekt końcowy. Aby uzyskać podgląd kodu projektu lub pobrać go na dysk swojego komputera, kliknij prawym przyciskiem myszy i wybierz “View Source”.

Najpierw tworzymy pierwszy element interfejsu użytkownika (SendView.mxml)

<?xml version="1.0" encoding="utf-8"?>
<s:Panel xmlns:fx="http://ns.adobe.com/mxml/2009"
		 xmlns:s="library://ns.adobe.com/flex/spark"
		 xmlns:mx="library://ns.adobe.com/flex/mx"
		 xmlns:spicefactory="http://www.spicefactory.org/parsley">

	<!-- SendView -->

	<fx:Script>
		<![CDATA[

			[Inject]
			[Bindable]
			public var model:SendModel;

		]]>
	</fx:Script>

	<fx:Declarations>
		<spicefactory:Configure/>
	</fx:Declarations>

	<s:Button label="Wyślij wiadomość" click="model.send()"/>

</s:Panel>

oraz towarzyszący mu model (SendModel.as).

package
{
	public class SendModel
	{
		[MessageDispatcher]
		public var sendMessage:Function;

		public function send():void
		{
			sendMessage(new Message("Wiadomość z SendView do ReceiveView"));
		}
	}
}

Komponent SendView zawiera przycisk “Wyślij wiadomość” (23). Kliknięcie przycisku generuje zdarzenie “click” i wywołanie metody “send()” znajdującej się w klasie SendModel (8). Komponent zawiera też publiczną właściwość “model” klasy SendModel (14). Przed jej definicją znajdują się dwa metatagi. Metatag [Bindable] jest standardowym elementem Flexa, natomiast [Inject] (12) spowoduje podpięcie przez Parsley’a obiektu klasy SendModel pod właściwość “model” klasy SendView. Dzięki temu będziemy mogli korzystać z metody “send()”. Na razie żaden obiekt klasy SendView nie jest w żaden sposób powiązany z obiektem klasy ModelView. Powiązanie to (czyli wstrzyknięcie zależności) nastąpi w momencie uruchomienia aplikacji. Komponent SendView zawiera też tag “Configure” (20). Dzięki niemu Parsley będzie wiedział o istnieniu SendView i umieści go w swoim kontekście.

Komponent SendModel zawiera właściwość “sendMessage” (6) opisaną metatagiem [MessageDispatcher] (5). Parsley wstrzyknie tutaj definicję funkcji pozwalającej na wysyłanie wiadomości obsługiwanych przez framework. W metodzie “send()” (10) wywołujemy tę funkcję podając jako jej parametr dowolny obiekt (w naszym przypadku jest to obiekt klasy Message – patrz niżej). Zaprezentowany tutaj mechanizm komunikacji nie jest jedynym jakim dysponuje Parsley (jest jednak najprostszy, więc go tutaj wykorzystujemy), w tym przypadku ważne jest, aby klasa obiektu przesyłanego za pomocą funkcji “sendMessage” była unikalna.

package
{
	public class Message
	{
		public var message:String = "";

		public function Message(m:String)
		{
			message = m;
		}
	}
}

Zajmijmy się teraz komponentami odbierającymi i przetwarzającymi wiadomość. Analogicznie mamy tutaj element interfejsu użytkownika (ReceiveView.mxml)

<?xml version="1.0" encoding="utf-8"?>
<s:Panel xmlns:fx="http://ns.adobe.com/mxml/2009"
		 xmlns:s="library://ns.adobe.com/flex/spark"
		 xmlns:mx="library://ns.adobe.com/flex/mx"
		 xmlns:spicefactory="http://www.spicefactory.org/parsley">

	<!-- ReceiveView -->

	<fx:Declarations>
		<spicefactory:Configure />
	</fx:Declarations>

	<fx:Script>
		<![CDATA[
			[Inject]
			[Bindable]
			public var model:ReceiveModel;
		]]>
	</fx:Script>

	<s:TextArea text="{model.message}" />

</s:Panel>

oraz towarzyszący mu model (ReceiveModel.mxml).

package
{
	public class ReceiveModel
	{
		[Bindable]
		public var message:String = "";

		[MessageHandler]
		public function sendMessageHandler(m:Message):void
		{
			this.message = m.message;
		}
	}
}

Komponent ReceiveView niewiele różni się od komponentu SendView. Zamiast przycisku mamy tutaj obiekt klasy TextArea (21), za pomocą którego wyświetlamy przesłany komunikat. Tutaj również stosujemy wstrzyknięcie zależności (obiektu klasy ReceiveModel) do właściwości “model” (15, 17). Tag “Configure” zapewnia, że Parsley będzie widział nasz komponent (10).

Komponent ReceiveModel zawiera metodę “sendMessageHandler” (9) oznaczoną metatagiem [MessageHandler] (8), która zostanie wywołana, gdy Parsley prześle wiadomość zawierającą obiekt klasy Message. To dlatego zwróciłem wcześniej uwagę na potrzebę unikalność tej klasy – nazwa klasy jest tutaj swego rodzaju kluczem, identyfikatorem.

Do tej pory utworzyliśmy dwa komponenty interfejsu użytkownika (SendView i ReceiveView) oraz powiązane z nimi modele (SendModel, ReceiveModel). Utworzyliśmy też klasę (Message), która będzie przenosiła treść komunikatu i jednocześnie będzie pełniła rolę klucza znanego nadawcy i odbiorcy (SendModel, ReceiveModel). Teraz trzeba skonfigurować framework do pracy z aplikacją.

Poinformowaliśmy Parsley’a o potrzebie obsługi dwóch komponentów interfejsu użytkownika (SendView i ReceiveView) korzystając z tagu “Configure”. Teraz przyszedł czas na podpięcie modeli. W tym celu tworzymy plik konfiguracyjny Parsley’a (Config.mxml):

<?xml version="1.0" encoding="utf-8"?>
<fx:Object xmlns:fx="http://ns.adobe.com/mxml/2009"
		   xmlns:s="library://ns.adobe.com/flex/spark"
		   xmlns:mx="library://ns.adobe.com/flex/mx" xmlns:local="*">

	<!-- Config -->

	<fx:Declarations>
		<local:SendModel />
		<local:ReceiveModel />
	</fx:Declarations>

</fx:Object>

Zwróć uwagę, że klasą bazową tego komponentu jest Object (2). W tagu “Declarations” (8) tworzymy instancje klas SendModel (9) i ReceiveModel (10). Od teraz Parsley będzie miał do nich dostęp.

Na końcu tworzymy główny plik aplikacji (ParsleyTest.mxml).

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009"
			   xmlns:s="library://ns.adobe.com/flex/spark"
			   xmlns:mx="library://ns.adobe.com/flex/mx"
			   xmlns:spicefactory="http://www.spicefactory.org/parsley"
			   xmlns:local="*">

	<s:layout>
		<s:HorizontalLayout/>
	</s:layout>

	<!-- ParsleyTest -->

	<fx:Declarations>
		<spicefactory:ContextBuilder config="Config"/>
	</fx:Declarations>

	<local:SendView width="50%" height="100%"/>
	<local:ReceiveView width="50%" height="100%"/>

</s:Application>

W tagu “Declarations” (14) tworzymy instancję klasy ContextBuilder (15) podając jako parametr nazwę klasy zawierającej konfigurację (Config). Na koniec tworzymy elementy wizualne aplikacji (SendView i ReceiveView) (18-19).

Uruchamiamy projekt i…. działa! :) Korzystając z dobrych wzorców projektowania utworzyliśmy prostą aplikację zawierającą obiekty luźno ze sobą powiązane, a jednak komunikujące się bez przeszkód.

Echem, przepraszam, jak to działa?

Po uruchomieniu aplikacji, w trakcie zdarzenia “Preinitialize”, zostaje uruchomiony Parsley. Na podstawie naszej konfiguracji (Config.mxml), tagów “Configure” (SendView i ReceiveView) oraz metatagów [Inject] Parsley wiąże ze sobą obiekty wstrzykując zależności. Parsley przejmuje też kontrolę nad komunikacją między komponentami (metatagi [MessageDispatcher] oraz [MessageHandler]).

Po kliknięciu przycisku “Wyślij wiadomość”, SendView wywołuje metodę “send()” w SendModel. SendModel wysyła wiadomość, którą przechwytuje Parsley i kieruje ją do ReceiveModel. ReceiveModel aktualizuje ReceiveView (za pomocą bindingu).

No i co dalej?

Aplikację omawianą w tym artykule znajdziesz tutaj. Po jej uruchomieniu kliknij prawym przyciskiem myszy i wybierz “View Source”, aby uzyskać dostęp do kodu źródłowego.

Podobny, ale nieco bardziej rozbudowany, projekt aplikacji znajduje się w pliku parsley-2.3.M3.zip w folderze “samples/helloworld”.

Więcej (o wiele więcej) na temat wykorzystania Parsley’a znajdziecie w obszernej dokumentacji.

This entry was posted in Flex 4, Frameworki, Tutoriale and tagged , , . Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.

One Trackback

  1. [...] Application Framework w praktyce (Krzysztof Satoła) W poście Parsley i Flex 4 w kilku krokach opisałem zasadę działania i najbardziej podstawowe mechanizmy frameworka aplikacji Parsley. W [...]

Post a Comment

You must be logged in to post a comment.