Eventos personalizados no Flex

Há um certo tempo tenho visto muita gente com uma certa dificuldade em desenvolver códigos com fraco acoplamento (baixa dependência entre objetos) nos fóruns e listas de discussão. No Flex, um tema ligado a isso é a construção de componentes, que envolve uma série de conceitos, inclusive a criação de eventos personalizados. É sobre isso que vou falar nesse artigo.

Os Custom Events são, como o nome diz, eventos personalizados (ohhh!!!). Uma das vantagem de criar eventos personalizados é a possibilidade de fazer com que um evento disparado carregue consigo uma determinada propriedade (ou várias delas) referentes ao evento ocorrido.

Imagine a seguinte situação: você tem um componente em MXML chamado Teste (caso tenham um nome mais criativo, coloquem nos comentários! :) ), e ele tem um botão, que vai incrementar o valor de uma variável privada. O código seria mais ou menos assim (o label serve só pra mostrar o valor da variável):

[as]



[Bindable] private var valor:int = 0;

private function incrementar():void {
this.valor++;
}
]]>






[/as]

Como podem ver, o lblValor1 mostrará o valor da variável ‘valor’ através de DataBinding, só para fazermos uma comparação mais pra frente.

Ao executar o código, vemos que, ao clicar no botão, a variável ‘valor’ é incrementada e o seu conteúdo mostrado no label lblValor1.

Agora vamos adicionar mais um label, que mostrará o conteúdo da variável ‘valor’ através do disparo de um evento:

[as]


[/as]

Bom, agora, o que vamos fazer é mostrar o conteúdo da variável ‘valor’ em lblValor2 através do disparo de um evento.

Primeiro, algumas alterações no código incial:

[as]



[Bindable] private var _valor:int = 0;

public function get valor():int {
return this._valor;
}

public function set valor ( v:int ):void {
this._valor = v;
}

private function incrementar():void {
this.valor++;
}
]]>








[/as]

O que mudou: a variável ‘valor’ mudou para ‘_valor’, e foram criados o ‘getter’ e o ‘setter’ dessa variável. Dessa forma, podemos continuar nos referindo à variável ‘_valor’ usando essas funções (repare no binding do lblValor1. Ainda funciona por causa do [Bindable] no getter!).

Agora entra o evento customizado: queremos atualizar o lblValor2 sempre que o valor da variável ‘_valor’ for alterado, usando um evento customizado. Então vamos ao código do evento (criei um arquivo chamado ChangeEvent.as, na pasta events do meu projeto):

[as]
package events
{
import flash.events.Event;

public class ChangeEvent extends Event
{
public function ChangeEvent ( type:String, bubbles:Boolean=false, cancelable:Boolean=false) {
super ( type, bubbles, cancelable );
}

override public function clone():Event {
return new ChangeEvent ( type );
}
}
}
[/as]

Explicando: o construtor simplesmente chama o construtor da classe Event, passando os mesmos parâmetros que recebeu. O método clone precisa ser implementado sempre que estendemos a classe Event, pois ele será usado quando um evento for disparado. A idéia do método clone é criar uma cópia do evento. Vamos usar esse conceito mais pra frente.

Da forma como está, o nosso evento não tem nada de especial. Somente faz o que qualquer instância de Event faria. Vamos incremetá-lo.

Como queremos usá-lo para informar quando o valor de uma variável muda, podemos colocar esse valor que mudou dentro do evento. Então vamos criar uma propriedade chamada ‘_novoValor’ com seu getter e setter. Agora o nosso evento está assim:

[as]
package events
{
import flash.events.Event;

public class ChangeEvent extends Event
{
private var _novoValor:int;

public function get novoValor():int {
return this._novoValor;
}

public function set novoValor ( v:int ):void {
this._novoValor = v;
}

public function ChangeEvent ( type:String, bubbles:Boolean=false, cancelable:Boolean=false) {
super ( type, bubbles, cancelable );
}

override public function clone():Event {
return new ChangeEvent ( type );
}
}
}
[/as]

Agora que já temos um Evento Customizado que tem a capacidade de carregar com ele um determinado valor inteiro, vamos utilizá-lo para avisar que o valor que queremos monitorar foi modificado.

Primeiro, vamos modificar o nosso setter que está no arquivo Teste.mxml para disparar o evento quando o valor for modificado. A função fica assim:

[as]
public function set valor ( v:int ):void {
this._valor = v;

// Instancia, configura e dispara o ChangeEvent
var evt:ChangeEvent = new ChangeEvent(“valorModificado”);
evt.novoValor = v;
dispatchEvent( evt );
}
[/as]

Dessa forma, sempre que a variável ‘_valor’ for modificada (através desse setter) um evento ChangeEvent será disparado, avisando todos os seus listeners que alguma coisa aconteceu.

O primeiro parâmetro do construtor do nosso evento (a variável type, do tipo String) é como se fosse o “nome” do evento. Imagine que você está disparando um evento do tipo ChangeEvent com o nome “valorModificado”. Na hora de criar o eventListener, você vai indicar que os eventos com esse “nome” devem ser escutados. É para isso que serve a propriedade type do construtor do evento.

Vamos voltar ao código. Agora vamos adicionar o eventListener. Para isso, vamos chamar uma função no createComplete da nossa aplicação (onde o EventListener será adicionado à aplicação) e uma função que será chamada sempre que um evento que está sendo “ouvido” pelo listener for disparado. As alterações são as seguintes:

[as]

private function iniciar():void {
addEventListener(“valorModificado”, valorModificado );
}

private function valorModificado ( event:ChangeEvent ):void {
lblValor2.text = event.novoValor.toString();
}
[/as]

Repare o seguinte: em iniciar(), está sendo adicionado um listener (“escutador”, em uma tradução porca) que ficará prestando atenção nos eventos com nome “valorModificado”. Ou seja, quando alguém gritar: “VALORMODIFICADOOOOOO” (evento disparado), a função valorModificado será chamada, passando para ela o evento em questão, com todas as suas propriedades.

Dessa forma, dentro da função ‘valorModificado(event:ChangeEvent)’, podemos acessar o novo valor através da propriedade novoValor, que foi definido dentro da classe ChangeEvent e foi configurado no setter da variável a ser monitorada.

Resumo da ópera: se você precisa que um evento carregue algum valor, crie um evento customizado com a propriedade desejada. Na hora de disparar esse evento, configure a propriedade desejada e você terá acesso a ela na função configurada através do eventListener.

Eu sei, esse exemplo foi muuuito simples. Mas a idéia é essa. Basta abstrair o conceito e aplicá-lo para a comunicação entre os componentes. Assim conseguimos ter um fraco acoplamento entre eles.

Observação 1: a classe ChangeEvent *NÃO* é uma classe do Flex, assim como o ChangeWatcher. Acabei dando um nome em inglês e espero que isso não confunda a cabeça de ninguém! =)

Observação 2: por questões de desempenho, não é aconselhavel fazer muita coisa dentro dos getters ou dos setters. Talvez esse seja um assunto para outro artigo =)

Segue o código-fonte completo:

[as]



import events.ChangeEvent;

[Bindable] private var _valor:int = 0;

private function iniciar():void {
addEventListener("valorModificado", valorModificado );
}

[Bindable]
public function get valor():int {
return this._valor;
}

public function set valor ( v:int ):void {
this._valor = v;

// Instancia, configura e dispara o ChangeEvent
var evt:ChangeEvent = new ChangeEvent("valorModificado");
evt.novoValor = v;
dispatchEvent( evt );
}

private function incrementar():void {
this.valor++;
}

private function valorModificado ( event:ChangeEvent ):void {
lblValor2.text = event.novoValor.toString();
}
]]>








[/as]


Poderia avaliar este artigo, por favor?

1 Estrela2 Estrelas3 Estrelas4 Estrelas5 Estrelas
Loading ... Loading ...

Posts relacionados

  • http://www.digows.com/ Rodrigo Pereira Fraga

    Parabéns pelo artigo, gostei da abordagem.

    Abraços!
    o/

  • http://www.digows.com/ Rodrigo Pereira Fraga

    Parabéns pelo artigo, gostei da abordagem.

    Abraços!
    \o/

  • Alberto

    Minha nossa {Rei} ficou bom pra #$%@#!&.

    Sabe como é né, os conceitos a gente tem na cabeça de tanto ler artigos.
    Poliformismo, encapsulamento, herança, poliformismo, bla, bla, bla, bla.
    Os exemplos normalmente são com Pessoa(jurídica,física), sapato(com suas propriedades tamanho, cor, etc), carro(cor, modelo, etc).
    Nada se compara com um exemplo simples e bem escrito, e ainda por cima com o código, como o que vc escreveu.

    Valeu.

  • Alberto

    Minha nossa {Rei} ficou bom pra #$%@#!&.

    Sabe como é né, os conceitos a gente tem na cabeça de tanto ler artigos.
    Poliformismo, encapsulamento, herança, poliformismo, bla, bla, bla, bla.
    Os exemplos normalmente são com Pessoa(jurídica,física), sapato(com suas propriedades tamanho, cor, etc), carro(cor, modelo, etc).
    Nada se compara com um exemplo simples e bem escrito, e ainda por cima com o código, como o que vc escreveu.

    Valeu.

  • Fabiel

    Otimo post !

  • Fabiel

    Otimo post !

  • http://www.apollo-ti.com/ Juliano Feltraco

    Caracas… muito bom mesmo…

    Simples mas suficiente para entender o conceito.

    Abraço

  • http://www.apollo-ti.com Juliano Feltraco

    Caracas… muito bom mesmo…

    Simples mas suficiente para entender o conceito.

    Abraço

  • Matheus

    poliformismo
    sdauidshauidsahuidashusadidhasiudhsaui

  • http://dsa Matheus

    poliformismo
    sdauidshauidsahuidashusadidhasiudhsaui

  • Thiago Viana

    Ainda se usa get e set?

    • http://www.elvis.eti.br/ Elvis Fernandes

      Como assim, @Thiago?

      Em ActionScript o get e o set são muito utilizados sim, principalmente para trabalhar com encapsulamento.

  • Thiago Viana

    Ainda se usa get e set?

    • http://www.elvis.eti.br Elvis Fernandes

      Como assim, @Thiago?

      Em ActionScript o get e o set são muito utilizados sim, principalmente para trabalhar com encapsulamento.

  • Lucas Moretto

    Muito bem explicado, você foi bem objetivo.

    Parabéns!

  • Lucas Moretto

    Muito bem explicado, você foi bem objetivo.

    Parabéns!

  • Pingback: Eventos do Flex ou Customizados - redeRIA | Agregador de noticias, artigos, tutoriais Flex, Flash, JavaFX, AJAX e Rich internet applications em geral!

  • Pingback: Eventos » Bruno bg + ADOBE FLEX