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:

  • 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 ApplicationGroupPanel. Flash Player na každém uzlu kontroluje, zda má na spuštěnou událost zaregistrovaný listener, pokud ano, listener zavolá.
  • Targeting Phase zahrnuje pouze cílový/spouštěcí komponent (target node). Na komponentu jsou zavolány registrovaný listenery.
  • Bubbling Phase probíhá od rodičovského uzlu cílového komponentu zpět ke kořenovému uzlu. Na obrázku PanelGroupApplication. 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 (ApplicationGroupPanelButton). 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.

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>