18

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] [/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] [/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] [/as]

Comments 18

  1. 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.

  2. 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.

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

  4. Pingback: Eventos » Bruno bg + ADOBE FLEX

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *