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! [Bindable] private var valor:int = 0; private function incrementar():void {
), 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]
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 { public function set valor ( v:int ):void { private function incrementar():void {
return this._valor;
}
this._valor = v;
}
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? |

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