10. dubna 2012

Flex, pár drobností

Při studiu na nedávnou Flexovou certifikaci jsem se musel poměrně hodně hluboko ponořit do Flexové dokumantace. A to jak do reference ActionScriptu, tak do konceptů a architektury samotného Flexu Using Flex. Důvod byl jednoduchý - nedostatek praxe jsem musel nahradit porozuměním.

Protože se mi architektura Flexu líbíla, rád bych se k němu vrátil a pro ten případ si tady chci zaarchivoval pár věcí, které mne zaujaly.

Bidirectional binding
Pokud chci mít obousměrné datové propojení dvou komponent, mám k dispozici tři způsoby. Buď je vzájemně provázat jednosměrným bindingem:
<s:TextInput id="input1" text="{input2.text}"/>
<s:TextInput id="input2" text="{input1.text}"/>
Nebo na zdroji říct, že propojení je obousměrné pomocí znaku zavináče (@):
<s:TextInput id="input1" text="@{input2.text}"/>
<s:TextInput id="input2"/>
Anebo použít tag <fx:Binding> s nastavenou twoWay property:
<fx:Binding source="input1.text"
            destination="input2.text"
            twoWay="true"/>

Event flow
Flex je framework postavený mmj. na Even-driven architekturě. Události zde proto hrají jednu z ústředních rolí. Pokud je na nějakém komponentu spuštěna (triggered) událost, má Flex definovány tři fáze, během kterých zjišťuje, zda události naslouchají nějaký event  listeneři:

Tři fáze event flow
  1. Capturing Phase probíhá od kořenového uzlu (root node) komponentového stromu až k rodičovskému uzlu cílového komponentu (target node). Na obrázku Application -> Group -> Panel. Flash Player na každém uzlu kontroluje, zda má na spuštěnou událost zaregistrovaný listener, pokud ano, listener zavolá.
  2. Targeting Phase zahrnuje pouze cílový/spouštěcí komponent (target node). Na komponentu jsou zavolány registrovaný listenery.
  3. Bubbling Phase probíhá od rodičovského uzlu cílového komponentu zpět ke kořenovému uzlu. Na obrázku Panel -> Group -> Application. Opět jsou zavolány registrované listenery.
Jak to všechno funguje ukazuje následující kód. V MXML je definován komponentový strom z obrázku (Application -> Group -> Panel -> Button). Ve fázi inicializace (funkce initializeHandler) jsou na komponenty navěšeny listenery, na každý dva - jeden pro fázi capturing, jeden pro fázi bubbling. Zbytek funkcí jsou event handlery, které vypisují text do debug konzole (metoda trace).
<?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"
           initialize="initializeHandler(event)">

  <fx:Script>
    <![CDATA[
      import mx.events.FlexEvent;

      protected function clickHandler(
                      event:MouseEvent):void {
        trace("Button has been clicked.");
      }

      protected function groupEventHandler(
                      event:Event):void {
        trace("Event has been dispatched to: "
                        + event.currentTarget);
      }

      protected function panelEventHandler(
                      event:Event):void {
        trace("Event has been dispatched to: 
                        + event.currentTarget);
      }

      protected function buttonEventHandler(
                      event:Event):void {
        trace("Event has been dispatched to: 
                        + event.currentTarget);
      }

      protected function initializeHandler(
                      event:FlexEvent):void {
        group.addEventListener(MouseEvent.CLICK,
                               groupEventHandler,
                               true);
        group.addEventListener(MouseEvent.CLICK,
                               groupEventHandler);
        panel.addEventListener(MouseEvent.CLICK,
                               panelEventHandler,
                               true);
        panel.addEventListener(MouseEvent.CLICK,
                               panelEventHandler);
        button.addEventListener(MouseEvent.CLICK,
                                buttonEventHandler,
                                true);
        button.addEventListener(MouseEvent.CLICK,
                                buttonEventHandler);
      }

    ]]>
  </fx:Script>

  <s:Group id="group">
    <s:Panel id="panel" title="Panel">
      <s:Button id="button"
                label="Button Event"
                click="clickHandler(event)"/>
    </s:Panel>
  </s:Group>

</s:Application>
Po kliknutí na tlačítko Button Event se na debug konzoli vypíše následující výpis (řádky jsou zalomeny). Jednotlivé barvy představují výše popsané fáze.
Event has been dispatched to: Work.ApplicationSkin2
    ._ApplicationSkin_Group1.contentGroup.group
Event has been dispatched to: Work.ApplicationSkin2
    ._ApplicationSkin_Group1.contentGroup.group.panel
Button has been clicked.
Event has been dispatched to: Work.ApplicationSkin2
    ._ApplicationSkin_Group1.contentGroup.group.panel
    .PanelSkin7._PanelSkin_Group1.contents
    .contentGroup.button
Event has been dispatched to: Work.ApplicationSkin2
    ._ApplicationSkin_Group1.contentGroup.group.panel
Event has been dispatched to: Work.ApplicationSkin2
    ._ApplicationSkin_Group1.contentGroup.group

HTTPService
Pro zaslání HTTP requestu a příjem odpovědi na/z nějaké URL obsahuje Flex třídu HTTPService. Třída funfuje asynchronně - metodou send() se odešle request a události result se nastaví handler, který zpracuje response. Celé je to jednoduché a elegantní:
<fx:Script>
  <![CDATA[
    import mx.rpc.events.ResultEvent;

    protected function init():void {
      categoryService.send();
    }

    protected function resultHandler(
                            event:ResultEvent):void {
      trace(event.result);
    }
  ]]>
</fx:Script>
<fx:Declarations>
  <s:HTTPService id="categoryService"
         url="http://www.flexgrocer.com/category.xml"
         resultFormat="e4x"
         result="resultHandler(event)"/>
</fx:Declarations>

Žádné komentáře:

Okomentovat