Avaliação de Aplicativos Modulares - Parte IV

Flex / Flex Builder No Comments »

Carregando e descarregando módulos

Para carregar e descarregar módulos você usa o métodos load() e unload() da classe ModuleLoader. Estes métodos não tem nenhum parâmetro; O ModuleLoader carrega ou descarrega o módulo que combina o valor da propriedade de uRL atual.
O exemplo seguinte carrega e descarrega o módulo quando você clicar o botão

<?xml version=”1.0″?><!– modules/ASModuleLoaderApp.mxml –><mx:Application xmlns:mx=”http://www.adobe.com/2006/mxml”>    <mx:Script>        <![CDATA[        import mx.modules.*;

        public function createModule(m:ModuleLoader, s:String):void {            if (!m.url) {                m.url = s;                return;            }            m.loadModule();        }

        public function removeModule(m:ModuleLoader):void {            m.unloadModule();        }        ]]>    </mx:Script>

    <mx:Panel title=”Module Example”        height=”90%”        width=”90%”        paddingTop=”10″        paddingLeft=”10″        paddingRight=”10″        paddingBottom=”10″    >        <mx:TabNavigator id=”tn”            width=”100%”            height=”100%”            creationPolicy=”auto”        >            <mx:VBox id=”vb1″ label=”Column Chart Module”>                             <mx:Button                    label=”Load”                    click=”createModule(chartModuleLoader, l1.text)”                />                <mx:Button                    label=”Unload”                    click=”removeModule(chartModuleLoader)”                />                <mx:Label id=”l1″ text=”ColumnChartModule.swf”/>                <mx:ModuleLoader id=”chartModuleLoader”/>                                         </mx:VBox>

            <mx:VBox id=”vb2″ label=”Form Module”>                <mx:Button                    label=”Load”                    click=”createModule(formModuleLoader, l2.text)”                />                <mx:Button                    label=”Unload”                    click=”removeModule(formModuleLoader)”                />                <mx:Label id=”l2″ text=”FormModule.swf”/>                <mx:ModuleLoader id=”formModuleLoader”/>            </mx:VBox>        </mx:TabNavigator>    </mx:Panel></mx:Application>

Fixando o local de um ModuleLoader ativa um chamada para o método loadModule(),
também. Isto acontece quando você primeiro criar um ModuleLoader com a
propriedade de uRL fixa.
Também acontece se você mudar o valor daquela propriedade.
O exemplo seguinte carrega os módulos sem chamar o método
loadModule() porque a propriedade de uRL é fixada na tag <mx:ModuleLoader>:

<?xml version="1.0"?><!– modules/URLModuleLoaderApp.mxml –><mx:Application xmlns:mx=”http://www.adobe.com/2006/mxml”>    <mx:Panel        title=”Module Example”        height=”90%”        width=”90%”        paddingTop=”10″        paddingLeft=”10″        paddingRight=”10″        paddingBottom=”10″    >

        <mx:Label width=”100%” color=”blue”            text=”Select the tabs to change the panel.”/>

        <mx:TabNavigator id=”tn”            width=”100%”            height=”100%”            creationPolicy=”auto”        >            <mx:VBox id=”vb1″ label=”Column Chart Module”>                <mx:Label id=”l1″ text=”ColumnChartModule.swf”/>                <mx:ModuleLoader url=”ColumnChartModule.swf”/>            </mx:VBox>

            <mx:VBox id=”vb2″ label=”Form Module”>                <mx:Label id=”l2″ text=”FormModule.swf”/>                <mx:ModuleLoader url=”FormModule.swf”/>            </mx:VBox>

        </mx:TabNavigator>    </mx:Panel></mx:Application>

Quando você carregar um módulo, o Flex assegura que existe só uma cópia de um módulo carregado, não importa quantas vezes você chama load() para aquele módulo.

Os módulos são carregados na child do aplicativo atual. Você pode especificar um aplicativo diferente usando a propriedade applicationDomain da classe ModuleLoader.

Quando duas classes do mesmo nome mas implementações diferentes são carregadas, o primeiro carregado é o que será usado.

Carregando módulos de diferentes servidores

Para carregar um módulo de um servidor em um aplicativo que roda em um servidor diferente, você deve estabelecer uma confiança entre o módulo e o aplicativo que vai carrega-lo.

Para permitir acesso através de domínios:

Em seu aplicativo, você deve chamar o método allowDomain() e especificar o target do domínio que carrega o módulo. Então, especifique o domínio no manipulador de evento preinitialize de seu aplicativo para assegurar que o aplicativo é instalado antes do módulo ser carregado.

1. No arquivo de domínio cruzado do servidor remoto onde seu módulo está, adicione uma entrada que especifica o servidor em que o aplicativo que carregará está rodando.

2. Carregue o arquivo cross-domain no servidor remoto no evento preinitialize de seu aplicativo.

3. No módulo carregado, chame o método allowDomain() de forma que pode comunicar com o carregador

O seguinte exemplo mostra o método init() do aplicativo carregado.

public function setup():void {    Security.allowDomain(”remoteservername”);    Security.loadPolicyFile(”http://remoteservername/crossdomain.xml”);    var request:URLRequest = new URLRequest(”http://remoteservername        /crossdomain.xml”);    var loader:URLLoader = new URLLoader();    loader.load(request);}

O seguinte exemplo mostra módulo carregado do método init():

public function initMod():void {    Security.allowDomain(”loaderservername”);}

O seguinte exemplo mostra o cross-domain que reside no servidor remoto:

<!-- crossdomain.xml file located at the root of the server --><cross-domain-policy>    <allow-access-from domain=”loaderservername” to-ports=”*”/></cross-domain-policy>

Avaliação de Aplicativos Modulares - Parte III

Flex / Flex Builder No Comments »

Compilando Módulos

Você compila o módulo como você compilaria qualquer aplicativo do Flex usando o comando mxmlc do compilador ou o compilador do Flex Builder. O comando seguinte é o mais simples comando mxmlc:
mxmlc MyModule.mxml
O resultado é um arquivo SWF que você carrega em seu aplicativo como um módulo. Você não pode executar o arquivo SWF do módulo como um aplicativo Flash independente ou executá-lo em uma janela do Browser. Deve ser carregado por um aplicativo flex como um módulo.


Controlando o tamanho do módulo

O tamanho do módulo varia baseado nos componentes e classes que são usadas no módulo. Por padrão, um módulo inclui todo código do framework que seus componentes dependem, que podem fazer módulos serem grandes ligando classes que sobrepõem com as classes do aplicativo.
Para reduzir o tamanho dos módulos, você pode instruir o módulo para externalizar classes que são incluídas pelo aplicativo. Este inclui classes personalizada e classes de frameworks. O resultado é que o módulo só inclui a classe que requer, enquanto o código framework e outro dependências são incluídas no aplicativo.
Para externalizar classes de frameworks, você gera um linker report do aplicativo que carrega os módulos, usando p comando mxmlc. Você entá usando este repot como entrada para a carga externa dos módulos na opção do compilador


Para criar um linker report:
1. Gere o linker report:
mxmlc -link-report=report.xml MyApplication.mxml
2. Compile o arquivo SWF da aplicação:
mxmlc MyApplication.mxml
3. Compile o módulo:
mxmlc -load-externs=report.xml MyModule.mxml


Recompilando módulos

Você deve recompilar os módulos se você fizer mudanças. Recompilando o aplicativo principal não ativa um recompilação dos módulos. Semelhantemente, se você mudar o arquivo de aplicativo, você não tem que recompilar os módulos, a menos que você faça mudanças que poderia afetar o linker report ou código comum.

NOTA: Se você externalizar o módulo de dependências usando a opção externa de carga, seu módulo não poderia ser compatível com versões futuras de Flex de Adobe. Você pode ter que recompilar o módulo. Para assegurar que um aplicativo de Flex futuro pode usar um módulo, compile aquele módulo com todas as classes requeridas. Isto também se aplica a aplicativos que você carrega dentro de outros aplicativos

Avaliação de Aplicativos Modulares - Parte II

Flex / Flex Builder No Comments »

Criando Módulos

Os módulos são classes somente como arquivos de aplicativo. Para criar um módulo em ActionScript, você cria um arquivo que estende a classe mx.modules.ModuleBase. Para criar um módulo em MXML, você estende a classe mx.modules.Module criando um arquivo cuja tag raiz é . Naquela etiqueta, assegure que você adiciona qualquer namespaces que são usados naquele módulo. Você também devia incluir uma tag de declaração de tipo no inicio do arquivo.
O exemplo seguinte é um módulo que inclui um controle de Gráfico:

<?xml version=”1.0″?><!– modules/ColumnChartModule.mxml –><mx:Module xmlns:mx=”http://www.adobe.com/2006/mxml” width=”100%” height=”100%” >    <mx:Script><![CDATA[        import mx.collections.ArrayCollection;        [Bindable]        public var expenses:ArrayCollection = new ArrayCollection([            {Month:”Jan”, Profit:2000, Expenses:1500},            {Month:”Feb”, Profit:1000, Expenses:200},            {Month:”Mar”, Profit:1500, Expenses:500}        ]);    ]]></mx:Script>    <mx:ColumnChart id=”myChart” dataProvider=”{expenses}”>        <mx:horizontalAxis>           <mx:CategoryAxis                dataProvider=”{expenses}”                categoryField=”Month”           />        </mx:horizontalAxis>        <mx:series>           <mx:ColumnSeries                xField=”Month”                yField=”Profit”                displayName=”Profit”           />           <mx:ColumnSeries                xField=”Month”                yField=”Expenses”                displayName=”Expenses”            />        </mx:series>     </mx:ColumnChart>     <mx:Legend dataProvider=”{myChart}”/></mx:Module>


Os módulos baseados em mxml podem carregar outros módulos. Aqueles módulos podem carregar outros módulos, e assim por diante.

Avaliação de Aplicativos Modulares - Parte I

Flex / Flex Builder No Comments »

Sobre Módulos

Os módulos são arquivos SWF que pode ser carregado e descarregado por um aplicativo. Eles não podem ser executados independentemente de um aplicativo, mas qualquer número de aplicativos pode compartilhar os módulos.

Os módulos permitem que você divida seu aplicativo em vários pedaços, ou módulos. O aplicativo principal, ou Shell, pode dinamicamente carregar outros módulos que requer, quando ele precisar deles. Ele não tem que carregar todos os módulos quando iniciar, nem tem que carregar quaisquer módulos se o usuário quer interagir com eles. Quando o aplicativo não mais precisa de um módulo, pode descarregar o módulo e liberá-lo da mémória .
Os aplicativos modulares têm as seguintes vantagens:

1. Menor carga inicial no tamanho do arquivo SWF.
2. Menor tempo de carga devido ao arquivo SWF ser menor.
3. Melhor encapsulação de aspectos relacionados de um aplicativo. Por exemplo, um “reporting”A característica pode ser separada em um módulo que você pode então trabalhar independentemente.

Benefícios dos módulos

Os módulos são semelhantes a Runtime Shared Libraries (RSLs) eles separam código no aplicativo e carregam arquivos SWF separadamente. Os módulos são muito mais flexíveis que RSLs porque módulos podem ser carregados e descarregados em tempo de execução e compilado sem o aplicativo.

Dois senários comuns em que usar módulos é benéfico são um aplicativo grande com caminhos de usuário diferente e um aplicativo de portal.
Um exemplo do primeiro cenário comum ser um enorme aplicativo de seguro que inclui milhares de telas, seguro vida, seguro de carro, seguro de saúde, seguro dental, viaje seguro, seguro animal e veterinário.Usando uma abordagem tradicional para aplicativo de Internet rica (RIA), você poderia construir um aplicativo monolítico com uma árvore hierárquica de classe MXML. A atividades de memória usada e iniciada para o aplicativo seria significante, e o tamanho do arquivo SWF cresceria com cada novo conjunto de funcionalidade.

Quando usado este aplicativo, porém, qualquer usuário acessa só um subconjunto das telas. Por refactoring as telas em grupos pequenos de módulos que são carregadas em demanda, você pode melhorar a apresentação vista do aplicativo principal e reduzir a memória usada. Também, quando o aplicativo é separado em módulos, a produtividade dos desenvolvedores pode aumentar devido a encapsulação melhor de projeto. Quando reconstruindo o aplicativo, os desenvolvedores também têm que recompilar só o módulo único em vez do aplicativo inteiro.
Um exemplo comum do segundo cenário é um sistema com um aplicativo de portal principal, escrito em ActionScript 3, isso fornece serviços para numeroso portlets. Portlets são configurados baseados em dados que é carregado em uma per-use basico. Usando a abordagem tradicional, você poderia construir um aplicativo que compila em todo conhecido portlets. Isto é ineficiente, ambos para publicar e desenvolver.

Usando módulos, você pode estabelecer uma interface que contém serviços de portal, e uma genérica portlet interface. Você pode usar dados XML para determinar que módulos carregará uma determinada sessão. Quando o módulo é carregado, você obtém um handle para uma classe factory dentro do módulo, e de que você cria uma instância de uma classe que implementa o portlet interface. Neste argumento, recompilação total é necessário só se houver mudança de interfaces .

Detalhe da API dos módulos

Os módulos implementam uma class factory com uma interface normal. O produto daquela class factory implementa uma interface conhecida por Shell, ou a Shell implementa uma interface conhecida por módulos.
Usando definições de interface compartilhada, estas interfaces compartilhadas reduzem fortemente as dependências entre a Shell e o módulo. Este fornece comunicação type-safe segura e obriga uma camada de abstração sem adicionar significativamente ao tamanho do arquivo SWF.
A imagem seguinte mostra à relação entre a shell e as interfaces dos módulos:

Criando Aplicações Modulares

Para criar um aplicativo modular, você cria classes separadas para cada módulo, mais no aplicativo que carrega os módulos.

Para criar uma aplicação modular:

1. Crie qualquer número de módulos. A tag raiz do arquivo de módulo baseado em MXML é . módulos baseados em actionscript estendem a classe ModuleBase.
2. Compile cada módulo como se fosse um aplicativo. Você pode fazer isto usando a linha de comando mxmlc do compilador ou o compilador do Adobe Flex Builder.
3. Crie uma classe de Aplicativo. Isto é tipicamente um arquivo MXML cuja tag raiz é , mas ele também pode ser um aplicativo ActionScript.
4. No arquivo de Aplicativo, use uma tag para carregar cada um dos módulos. Você também pode fazer isto usando o método load() da classe mx.modules.ModuleLoader. Para classes que estendem ModuleBase, você deve usar os métodos da classe ModuleManager para carregá-lo.

Um pouco a fundo em trabalhar com E4X

Flex / Flex Builder No Comments »

As versões mais recente do Flash Player da Adobe sustentam E4X, o qual é um conjunto de extensões de linguagem de programação que adiciona XML nativo suportado por ActionScript. Estas extensões permitem que você trabalhe com XML no Flex 2 usando os mesmos operadores comuns que você já conhece. Mais adiante, eles adicionam um conjunto pequeno de novos operadores para lidar com operações comuns, como procurar e filtrar..
Nesta seção, você consegue uma avaliação dos operadores de centro e extensões para usar E4X. Entendendo que estas capacidades muito realçarão sua habilidade de trabalhar com XML dentro do Flex 2.


Você pode agora declarar XML literais como você faria com qualquer integer ou string:

var orderInfo:XML = <order>
<item id=’1′>
<menuName>burger</menuName>
<price>3.95</price>
</item>
<item id=’2′>
<menuName>fries</menuName>
<price>1.45</price>
</item>
</order>;

Você pode usar ponto e sintaxe de array já comum para a maioria das linguagens de programação, e certamente para usuários de ActionScript, acessar dados em uma estrutura XML:

trace( orderInfo.item[1].menuName ); //fries
Voce pode usar o operador .@ para acessar atributos de um nó XML:
trace( orderInfo.item[1].@id ); //2

Você pode recuperar uma lista de nós como uma lista XML:

trace( orderInfo.item.menuName );
//<menuName>burger</menuName>
//<menuName>fries</menuName>

Você pode usar o operador descendente .. para procurar abaixo pelo XML:

trace( orderInfo..price );
//<price>3.95</price>
//<price>1.45</price>

Você também pode usar predicado para filtrar seus resultados baseados em condições:

trace( orderInfo.item(@id==2).price );
//<price>1.45</price>

var myID:int = 2;
trace( orderInfo.item(@id==myID).price );
//<price>1.45</price>

Para o número crescente de desenvolvedores que usa XML como dados dentro de seus aplicativos, E4X é crítico para desenvolvimento de aplicativo diariamente .
Existe uma captura pequena, porém. E4X é uma série de operadores—e em ActionScript 3 você não tem qualquer caminho para avaliar uma expressão representada como uma string em runtime. Tome a seguinte string como um exemplo:

var myAddString:String = “2 + 2″;

Não existe um caminho para especificar que ActionScript avalia a expressão e retorna a resposta “4.” Você também não tem a habilidade de avaliar a expressão seguinte contra XML dentro da memória:

var myExpression:String = “..item.(@id==2)..price”;

Algum de vocês poderia estar perguntando por que alguém quereria fazer isto? Boa pergunta. Porém, em vez de responder, vamos fornecer um exemplo específico onde esta característica é extremamente útil e deixa os milhares de outras respostas possíveis para você.
Motivação usando E4X: Uma simples aplicação
Você tem um aplicativo que retorna os seguintes dados de XML que você precisa exibir em um DataGrid:

<mx:XML id=”order”>
<order>
<item id=’1′>
<menuName>burger</menuName>
<criticalInfo>

<vegetarian>false</vegetarian>
<containsPeanuts>false</containsPeanuts>
</criticalInfo><salesInfo>
<quantity>3</quantity>
<price>3.95</price>
<lineTotal>11.85</lineTotal></salesInfo>
</item>
<item id=’2′>
<menuName>fries</menuName>
<criticalInfo>
<vegetarian>true</vegetarian>
<containsPeanuts>false</containsPeanuts>
</criticalInfo>
<salesInfo>
<quantity>4</quantity><price>1.45</price><lineTotal>5.80</lineTotal></salesInfo>
</item>
</order></mx:XML>

No Flex 2, o DataGrid pode aceitar XML diretamente como um dataProvider. Então você pode rapidamente preencher seu grid para exibir as informações:

<mx:DataGrid dataProvider=”{order.item}”>
<mx:columns>
<mx:DataGridColumn headerText=”Name” dataField=”menuName”/
<mx:DataGridColumn headerText=”Vegetarian” dataField=”criticalInfo.vegetarian”/> <mx:DataGridColumn headerText=”Peanuts” dataField=”criticalInfo.containsPeanuts”/> <mx:DataGridColumn headerText=”Quantity” dataField=”salesInfo.quantity”/>
<mx:DataGridColumn headerText=”Price” dataField=”salesInfo.price”/>
<mx:DataGridColumn headerText=”Line Total” dataField=”salesInfo.lineTotal”/>
</mx:columns>
</mx:DataGrid>

Usando suas novas habilidades de E4X, você rapidamente adiciona um dataField para cada uma das colunas com o caminho apropriado para seus dados e teste seu aplicativo. Porém, Nome é a única coluna de seu DataGrid que exibe dados (veja Figura 1). Olhando para os arquivos de ajuda adicional, você descobre que a propriedade dataField do DataGridColumn aceite uma string, não uma expressão. Então como você exibirá as outras colunas cujos dados existem em um nível abaixo do primeiro nível na hierarquia de XML?

Exemplo de uma solução baseada no E4X

Para aqueles que são muito familiarizados com Datagrids, sua primeira reação poderia ser em criar um labelFunction para cada do DataGridColumns

Figure 2. DataGrid com o diferente labelFunctions para cada coluna
Boas notícias: Este trabalho de abordagem. Adicionando um labelFunction para cada coluna, você pode controlar como as colunas mostram seus dados e usam E4X para derivar o valor apropriado de seus dados de XML:

<mx:Script>
<![CDATA[

import mx.controls.dataGridClasses.DataGridColumn;
protected function displayVegetarian( row:Object, column:DataGridColumn ):String {
return row.criticalInfo.vegetarian;
}

protected function displayPeanuts( row:Object, column:DataGridColumn ):String {
return row.criticalInfo.containsPeanuts;
}

protected function displayQuantity( row:Object, column:DataGridColumn ):String {
return row.salesInfo.quantity;
}

protected function displayPrice( row:Object, column:DataGridColumn ):String {
return row.salesInfo.price;
}

protected function displayLineTotal( row:Object, column:DataGridColumn ):String {
return row.salesInfo.lineTotal;
}
]]>
</mx:Script>

<mx:DataGrid dataProvider=”{order.item}” width=”450″>
<mx:columns>
<mx:DataGridColumn headerText=”Name” dataField=”menuName”/>
<mx:DataGridColumn headerText=”Vegetarian” labelFunction=”displayVegetarian”/>
<mx:DataGridColumn headerText=”Peanuts” labelFunction=”displayPeanuts”/>
<mx:DataGridColumn headerText=”Quantity” labelFunction=”displayQuantity”/>
<mx:DataGridColumn headerText=”Price” labelFunction=”displayPrice”/>
<mx:DataGridColumn headerText=”Line Total” labelFunction=”displayLineTotal”/>
</mx:columns>
</mx:DataGrid>

Enquanto este código alcança o resultado pretendido, requer um labelFunction separado para cada coluna—então, não é uma solução muito escalável. Se você tiver muitas colunas ou muitos Datagrids diferentes dentro de seu aplicativo, tendo um labelFunction para cada um rapidamente ficará intratável.

Uma solução melhor é escrever uma função de tag única que seu aplicativo podia reusar para toda coluna do DataGrid. O flex fornece aos desenvolvedores todas as ferramentas para realizar esta tarefa. Porém, um pouco de assembly é exigido.

Para usar uma função label única, você deve fazer o seguinte:

Especifique uma expressão diferente para cada DataGridColumn como uma string.
Recupere aquela expressão da função label única.
Analise gramaticalmente a string de expressão e derive os dados corretos do XML.
Retorne aquelas informações como uma string que o DataGrid pode exibir.
Primeiro, crie uma função label única para exibir o XML, chamado displayXMLData:

protected function displayXMLData( row:Object, column:DataGridColumn ):String {
return “”;
}

Próximo, mude as colunas em seu DataGrid usando esta função label. Também, adicione a propriedade dataField para cada uma das colunas. Use esta propriedade dataField, como acima, para especificar o caminho do E4X para seus dados:

<mx:DataGrid dataProvider=”{order.item}” width=”450″>
<mx:columns>
<mx:DataGridColumn headerText=”Name” dataField=”menuName”/>
<mx:DataGridColumn headerText=”Vegetarian” dataField=”criticalInfo.vegetarian” labelFunction=”displayXMLData”/>
<mx:DataGridColumn headerText=”Peanuts” dataField=”criticalInfo.containsPeanuts” labelFunction=”displayXMLData”/>
<mx:DataGridColumn headerText=”Quantity” dataField=”salesInfo.quantity” labelFunction=”displayXMLData”/>
<mx:DataGridColumn headerText=”Price” dataField=”salesInfo.price” labelFunction=”displayXMLData”/>
<mx:DataGridColumn headerText=”Line Total” dataField=”salesInfo.lineTotal” labelFunction=”displayXMLData”/>
</mx:columns>
</mx:DataGrid>

O método displayXMLData que você criou acima levam dois parâmetros: A fila e coluna . A última é uma referência para o DataGridColumn chamando o método. Em outras palavras, quando o DataGrid tentar exibir dados para a coluna de Quantidade, chama o método displayXMLData e passa pra ele uma referência para a fila de dados que é atualmente difícil para exibir e uma referência para a entrada da Quantidade DataGridColumn.

De dentro o método displayXMLData, você pode acessar quaisquer das propriedades do DataGridColumn, inclusive o dataField. Então quando o displayXMLData for chamado pelo DataGrid exibi a coluna de Quantidade, a propriedade column.dataField conterá a String salesInfo.quantity. Isto é o valor que você passou como um parâmetro para a coluna de DataGrid no código acima. Deste modo, uma função label única pode determinar que dados retornar.

Este resolve os primeiros dois objetivos listados acima. Porém, você necessita analisar gramaticalmente a expressão dataField e retornar os dados apropriados. Este requer algum conhecimento adicional sobre a nova classe XML em Flex 2.

Acima, os operadores de E4X foram demonstrados como um caminho para derivar dados de uma estrutura XML. Porém, também é possível usar os métodos da classe XML para realizar muitas destas mesmas ações. Aqui estão dois exemplos:
Operador e método descendente

order..item is equivalent to order.descendants( “item” );

Atribua operador e método

order.item.@id is equivalent to order.item.attribute(”id”);

Analisando gramaticalmente a expressão E4X passou para a propriedade dataField da coluna e chamou os métodos de XML apropriado, você pode realizar a mesma meta avaliando uma expressão hard-coded de E4X. A figura 3 mostra um quadro simplificados desta abordagem.

Figure 3. Versão visual do workflow
As operações importantes são como segue:

•Separe a expressão em cláusulas nos períodos únicos
•loop pelas cláusulas da esquerda para a direita
•Se a cláusula contém um conjunto de parenteses, é um filtro de predicado e você precisa fazer uma comparação
•Se a cláusula contém um operador descendente, chame o método descendente nos resultados até agora com a string à direita do operador
•Outro, use a sintaxe de ordem sustentada para estreito os resultados até agora pela cláusula
•Repita o laço até que você avaliou toda cláusula e retornou o resultado

Como você pode ver, não existe qualquer mágica em analisar gramaticalmente esta expressão e avaliando o XML. É só uma tarefa repetitiva—e, como todas as tarefas repetitivas, devia ser escrito uma vez e usado repetidamente. Este código está disponível para você no arquivo ZIP: Uma classe estática chamando o E4XParser.
Você pode usar E4XParser para terminar a tarefa que você começou acima:

<mx:Script>
<![CDATA[
import mx.controls.dataGridClasses.DataGridColumn;
import net.digitalprimates.utils.E4XParser;

protected function displayXMLData( row:Object, column:DataGridColumn ):String {
return E4XParser.evaluate( row, column.dataField );
}
]]>
</mx:Script>

Você agora tem uma função única capaz de retornar os resultados corretos de qualquer coluna (veja Figura 4) não importando a profundidade na hierarquia, tão longa como o dataField é fornecido para o DataGridColumn como uma expressão de E4X válido.

Figure 4. DataGrid com o diferente labelFunctions para cada coluna

Onde ir daqui

Neste artigo, você construiu uma função que foi capaz de retornar o XML correto em uma representação de string de uma expressão de E4X. Enquanto isto é um bom uso da tecnologia, é realmente somente o ponto de partida. Usando o mesmo conceito, você pode derivar expressões de E4X de tabelas de banco de dados ou mensagens de servidor, concatenando strings por interface de usuário gestos, ou diretamente de input de usuário.

No arquivo ZIP ( click para baixar ) (veja a seção de Requisitos no princípio), eu incluo uma ferramenta de depuração E4X (veja Figura 5). Ela demonstra a habilidade de pegar XML e uma expressão E4X ambos de input de usuário, avalie a expressão XML, e retorne o resultado em uma representação de árvore e em XML cru. É uma ferramenta útil para expressões de depuração E4X. Porém, também é uma grande demonstração do poder de E4X dinamicamente-avaliado.

Figure 5. E4X debugging tool

Criando um leitor de RSS Feed - Parte II

Ruby on Rails No Comments »

Inserindo um componente HTTPService

Para o leitor de blog nesta lição, você recuperará posts do blog do Matt Chotin em http://weblogs.macromedia.com/mchotin/index.xml em um agregador de notícias de um site da web. Matt é um gerente de produto na equipe Flex e escreve sobre Flex em seu blog.

Você pode usar o componente HTTPService para acessar o XML que alimenta e recupera informações sobre posts recentes. O componente permite que você envie um pedido HTTP GET ou POST, e então recupere os dados retornados na resposta.

  1. No modo Source , entre com a seguinte tag <mx:HTTPService> imediatamente depois da tag aberta<mx:Application>:

    <mx:HTTPService    id=”feedRequest”    url=”http://weblogs.macromedia.com/mchotin/index.xml”    useProxy=”false”/>

    A propriedade URL especifica o local do arquivo solicitado, neste caso o feed RSS 2.0 do blog do Matt Chotin. Quando esse tutorial foi escrito, o URL ainda estava era válido, mas você devia verificar e ter certeza que ele não mudou. Você deve usar o RSS mais recente 2.0 listado à direita do blog em http://www.adobe.com/go/mchotinblog.

    NOTA
    Se você quiser, poderá usar o seguinte alias no componente: http://www.adobe.com/go/flex_blogfeed.

    A propriedade useProxy especifica que você não quer usar um proxy em um servidor. O domínio onde o blog do Matt está localizado tem uma instalação crossdomain.xml, então o flash player pode acessar as fontes de dados remotas neste servidor, inclusive RSS feeds.

    O próximo passo é iniciar o aplicativo para enviar um pedido para o URL especificado. Você decide enviar o pedido automaticamente sempre que o aplicativo começa, como segue.

  2. Na tag <mx:Application>, adicione a seguinte propriedade creationComplete (in bold):

    <mx:Application xmlns:mx=http://www.adobe.com/2006/mxmllayout=”absolute” creationComplete=”feedRequest.send()” >
  3. Quando seu aplicativo terminar de carregar, o componente HTTPService chama o método send(). O método faz um pedido HTTP GET ou POST para o URL especificado, e uma resposta de HTTP é retornada. Neste caso, o RSS feerd retorna dados XML.

    Próximo, você quer verificar se o aplicativo está recuperando o RSS feed com sucesso. Você pode fazer isto no controle de tag, como segue.

  4. Na tag <mx:Panel>, renomeie o valor da propriedade title (”Blog Reader”) pela seguinte expressão(in bold):

    title=”{feedRequest.lastResult.rss.channel.title}

    Esta expressão liga o campo título para o controle de Painel. A expressão reflete a estrutura do XML. Quando XML é retornado a um componente HTTPService, o componente analisa gramaticalmente isto em um objeto de ActionScript chamado lastResult. A estrutura do objeto lastResult reflete a estrutura do XML. Para verificar a estrutura do XML, carregue o arquivo XML RSS feed ( http://www.adobe.com/go/flex_blogfeed) e abra-o no navegador.

    A estrutura geral do XML é a seguinte:

    <rss>    <channel>        <title>        other child nodes of <channel>        <item>            <title>            other child nodes of <item>        </item>        …

    Alguns nodos têm nodos filhos contendo dados, inclusive o nodo “title” é um nodo filho de channel. O lastResult do componente HTTPService (feedRequest.lastResult) reflete esta estrutura:

    feedRequest.lastResult.rss.channel.titleSeu código deve parecer com o exemplo seguinte:
    <?xml version=”1.0″ encoding=”utf-8″?><mx:Application xmlns:mx=”http://www.adobe.com/2006/mxml”    layout=”absolute”    creationComplete=”feedRequest.send()” >
    
        <mx:HTTPService        id=”feedRequest”        url=”http://weblogs.macromedia.com/mchotin/index.xml”        useProxy=”false” />
    
        <mx:Panel x=”10″ y=”10″ width=”475″ height=”400″ layout=”absolute”        title=”{feedRequest.lastResult.rss.channel.title}”>
    
            <mx:DataGrid x=”20″ y=”20″ id=”dgPosts” width=”400″>            <mx:columns>                <mx:DataGridColumn headerText=”Column 1″ dataField=”col1″/>                <mx:DataGridColumn headerText=”Column 2″ dataField=”col2″/>                <mx:DataGridColumn headerText=”Column 3″ dataField=”col3″/>            </mx:columns>        </mx:DataGrid>
    
            <mx:LinkButton x=”20″ y=”225″ label=”Read Full Post”/>        <mx:TextArea x=”20″ y=”175″ width=”400″/>    </mx:Panel>
    
    </mx:Application>
  5. Salve o arquivo, espere até que o Flex Builder termine de compilar o aplicativo, e então clique no botão Run na barra de ferramentas para iniciar o aplicativo. Se você estiver usando a configuração de plug-in do Flex, Selecione Run > Run As > Flex Application.

    Um Browser abrirá e executará o aplicativo. O título do blog, Matt Chotin, deve aparecer como o título do controle de Painel, indicando que o aplicativo com sucesso recuperou dados do RSS feed.

    NOTA
    Pode haver uma demora de alguns segundos antes do título aparecer enquanto o aplicativo está contactando o servidor.

Criando um leitor de RSS Feed - Parte I

Flex / Flex Builder No Comments »

Inserindo e posicionando um leitor de blog

Nesta seção, você cria o layout de seu leitor blog.

Com seu projeto Lessons selecionado na visão Navigator, selecione File > New > MXML Application e crie um arquivo chamado BlogReader.mxml.

NOTA
Com a finalidade destas lições, vários arquivos de aplicativo são usados em um simples projeto do Flex Builder. Porém, é boa prática ter só um arquivo MXML por projeto.

Designe o BlogReader.mxml como arquivo padrão para ser compilado click com o botão direito sobre o arquivo e selecione Fixar Como Aplicativo Padrão menu de contexto.

Em modo Design, arraste um recipiente Panel no layout da categoria de Components View, e então fixe as propriedades de Panel seguinte na aba Propriedades:

Title: Blog Reader
Width: 475
Height: 400
X: 10
Y: 10

No Design mode, adicione os seguintes controles no containet Panel arrastando-os da aba components View:

DataGrid
TextArea
LinkButton

Use o mouse para organizar os controles no layout em uma coluna vertical, alinhando a esquerda.

Selecione o controle DataGrid e fixe as propriedades seguintes:

Id: dgPosts
X: 20
Y: 20
Width: 400

Selecione o TextArea e fixe as seguintes propriedades:

X: 20
Y: 175
Width: 400

Selecione o LinkButton e fixe as seguintes propriedades:

Label: Read Full Post
X: 20
Y: 225

O layout deve parecer com o exemplo seguinte:

Troque para o modo Source clicando no botão na barra de ferramentas do editor.

O arquivo BlogReader.mxml deverá ter o seguinte código MXML:

<?xml version=”1.0″ encoding=”utf-8″?><mx:Application xmlns:mx=”http://www.adobe.com/2006/mxml” layout=”absolute”>    <mx:Panel x=”10″ y=”10″ width=”475″ height=”400″ layout=”absolute”        title=”Blog Reader”>        <mx:DataGrid x=”20″ y=”20″ id=”dgPosts” width=”400″>            <mx:columns>                <mx:DataGridColumn headerText=”Column 1″ dataField=”col1″/>                <mx:DataGridColumn headerText=”Column 2″ dataField=”col2″/>                <mx:DataGridColumn headerText=”Column 3″ dataField=”col3″/>            </mx:columns>        </mx:DataGrid>        <mx:LinkButton x=”20″ y=”225″ label=”Read Full Post”/>        <mx:TextArea x=”20″ y=”175″ width=”400″/>    </mx:Panel></mx:Application>

Salve o arquivo, espere até que o Flex Builder termine de compilar o aplicativo, e então clique no botão Run na barra de ferramentas para iniciar o aplicativo. Se você estiver usando a configuração de plug-in do Flex, Selecione Run > Run As > Flex Application.

Um browser abrirá e executará a aplicação.

NOTA:
O Browser deve ter o Flash player 9 instalado para funcionar o aplicativo. Você tem a opção de instalar o Flash Player 9 selecionando browsers quando você instala o Flex. Para trocar para um Browser com Flash Player 9, no Flex Builder selecione Window > Preferences > General > Web Browser.

O aplicativo não exibe quaisquer informações de blog ainda.

O próximo passo é recuperar informações recente sobre posts do blog. Você pode usar um componente de serviço chamado RPC HTTPService para realizar esta tarefa.

Usando Eventos

Flex / Flex Builder No Comments »

Usando eventos no Flex é um processo de dois passos. Primeiro, você escreve uma função ou método de classe, conhecida como listener event handler, que responde aos eventos. A função freqüentemente acessa as propriedades do objeto de Evento ou alguns outros cenários do estado de aplicativo. A assinatura desta função normalmente inclui um argumento que especifica o tipo de evento que está sendo passado .

O exemplo seguinte mostra uma função simples de event listener que reporta quando um controle ativar o evento que está escutando:

<mx:Script><![CDATA[    import mx.controls.Alert;    function myEventListener(event:Event):void {        Alert.show(”An event occurred”);    }]]></mx:Script>

Segundo, você registra aquela função ou método de classe com um display list object usando o método addEventListener(), como o exemplo seguinte mostra:

myButton.addEventListener(MouseEvent.CLICK, myEventListener);

A maioria dos controles Flex simplificam registro de listener permitindo a vocêespecificar o listener dentro da tag MXML. Por exemplo, em vez deusar o addEventListener() para especificar uma função listener para o eventoclick do controle de Botão, você especifica isto no atributo click da tag <mx:Button>:

<mx:Button id="b1" label="Click Me" click="myEventListener()"/>

Isto é equivalente ao método addEventListener() no exemplo anterior. Porém, a melhor prática é usar o método addEventListener(). Este método dá a você controle maior sobre o evento deixando você configurar as prioridades e capturar cenários, e uso constantes de evento. Além de, se você usar addEventListener() adicionar um listener, você pode usar removeEventListener() remover o listener quando você não mais precisar dele. Se você adicionar um event listener inline, você não pode chamar removeEventListener() naquele listener.

Todo tempo um controle gera um evento, o Flex cria um objeto de Evento que contém informações sobre aquele evento, inclusive o tipo de evento e uma referência para o dispatching control. Para usar o objeto de Evento, você especifica-o como um parâmetro na função event listener, como o exemplo seguinte mostra:

import mx.controls.Alert;function myEventListener(e:Event):void {    Alert.show(”An event of type ” + e.type + ” occurred.”);}

Se você quiser acessar o objeto de Evento em um event listener que foi ativado por um inline evento, você deve adicionar o palavra-chave de evento dentro da etiqueta de MXML de forma que o Flex explicitamente passa-o para o listener, como o exemplo seguinte mostra:

<mx:Button label="Click Me" id="button1" click="myInlineListener(event)”/>

Você não obrigado a usar o objeto de Evento em uma função listener. O exemplo seguinte cria duas funçãoes de event listener e registra-os com os eventos de um ComboBox. O primeiro event listener, openEvt(), não pega nenhum argumento. O segundo manipulador de evento, changeEvt(), leva o objeto de Evento como um argumento e usa este objeto para acessar o valor de selectedIndex do ComboBox que disparou o evento.

<?xml version="1.0"?><mx:Application xmlns:mx=”http://www.adobe.com/2006/mxml”>    <mx:Script><![CDATA[        function openEvt():void {            forChange.text=”";        }        function changeEvt(e:Event):void {            forChange.text=e.currentTarget.value + ” ” +                e.currentTarget.selectedIndex;        }    ]]></mx:Script>    <mx:ComboBox open=”openEvt()” change=”changeEvt(event)”>        <mx:dataProvider>            <mx:Array>                <mx:String>AK</mx:String>                <mx:String>AL</mx:String>                <mx:String>AR</mx:String>            </mx:Array>        </mx:dataProvider>    </mx:ComboBox>    <mx:TextArea id=”forChange” width=”150″/></mx:Application>

Especificando o objeto Event

Você especifica o objeto na assinatura da função listener como tipo Event, como o exemplo seguinte mostra:

function myEventListener(e:Event):void { … }

Porém, se você quiser acessar propriedades que são específicas para o tipo de evento que foi despachado, você deve ao invés especificar um tipo de evento mais específico, como ToolTipEvent ou KeyboardEvent, como o exemplo seguinte mostra:

import mx.events.ToolTipfunction myEventListener(e:ToolTipEvent):void { … }

Em alguns casos, você precisa importar da classe de Eventos em seu bloco ActionScript.

A maioria de objetos têm eventos específicos que estão associados com eles, e a maior parte deles podem despachar mais de um tipo de evento.

Se você declarar um evento do tipo Event, você pode lança-lo para um tipo mais específico para acessar seu evento-propriedades específicas.

Acessando a propriedade de objeto

Os objetos de evento incluem uma referência para a instância do componente (ou target). Então, você pode acessar todas as propriedades e métodos daquela instância em um event listener. O exemplo seguinte acessa o iD do botão que ativou o evento:

import mx.controls.Alert;function myEventListener(e:Event):void {    Alert.show(”The button ” + e.currentTarget.id +        ” was clicked”);}

Chamando métodos e acessando propriedades na target atual pode ser confuso. O tipo da propriedade currentTarget é DisplayObject. Porque ActionScript é fortemente digitado, você pode chamar event.currentTarget.methodName() só se methodName for um método definido em DisplayObject. O mesmo solicita propriedades. Você pode acessar event.currentTarget.property só se a propriedade é definida em DisplayObject. Se você tentar chamar outro método no currentTarget (por exemplo, o método getStyle()), o Flex retorna um erro. O getStyle() é definido em UIComponent, uma subdivisão de classe de DisplayObject. Então, você deve lançar currentTarget para UIComponent antes de chamar o getStyle(), como o exemplo seguinte mostra:

function myEventListener(e:Event):void {    UIComponent(e.currentTarget).getStyle(”color”);}

Você também pode acessar métodos e propriedades do objeto, que contém uma referência para o nodo atual na lista de exibição. Para mais informações.