[RESOLVIDO] Amarrando eventos com systemManager no Adobe Flex

Bom dia Pessoal,

       Estou usando o adobe flex e tenho uma duvida com respeito a disparar eventos, na verdade eu tenho um evento de uma janela para outra, eles estao na mesma displaylist, porem nao consigo disparar o evento por borbulhamento, entao usei a seguinte alternativa sugerida por um amigo, na janela que dispara o evento eu fiz o seguinte codigo:
systemManager.dispatchEvent("meuevento...");

e na janela que tem o metodo que é responsavel em si por capturar o evento disparado eu fiz o seguinte:

systemManager.addEventListener(etc...);

tudo esta funcionando perfeitamente bem, eu estou usando o cairngorm neste projeto mas nao gostei da ideia de colocar estes dados que estao sendo transferidos entre janelas no meu model locator, por serem dados bem banais e estarem associados com cada registro no banco de dados, na verdade um cliente ou funcionario poe ter diversos telefones, e existe uma funcao especifica para adicionar um telefone para cada cliente, ouvi falar algo em disparar este evento por borbulhacao, mas nao consegui ir mais fundo no assunto, entao gostaria de saber a opiniao de voces, acham que deveria continuar usando systemManager? eu particularmente tenho a idéia de ser uma coisa um tanto feia de ser feita, porem nao encontrei outras alternativas.

Abraços

André Martins

André,

Acho que você não está entendendo muito bem a idéia dos eventos no Flex. No outro post seu, que eu e o Thiago respondemos, estava explicando bem essa parte de como o evento vai “passar” entre os seus componentes. Adicionar o listner e disparar o evento no systemManager é mais uma “gambiarra”, assim como adicionar e disparar ele no Application.application, como algumas pessoas fazem. Não fica legal fazer dessa maneira pois você está passando a responsabilidade de controlar seus eventos da aplicação toda para o systemManager, que não foi feito para isso. Para saber mais sobre ele, leia a documentação em:

http://livedocs.adobe.com/flex/3/langref/mx/managers/SystemManager.html

Para explicar melhor, vamos criar uma aplicação simples que tem duas telas: cadastro e lista de telefones.
A hierarquia vai ser assim:

  • Application (Sua tela inicial, o Index)
    — Cadastro de Telefones
    ----- Componentes do cadastro
    ----- etc etc etc…
    — Lista de Telefones
    ----- Componentes da lista
    ----- etc etc etc…

Repare que os componentes “Cadastro de Telefones” e “Lista de Telefones” estão no mesmo nível da hierarquia, portanto somente dar o dispatch em um deles não vai fazer com que o evento chegue no outro.

Agora, vamos passar os telefones cadastrados do Cadastro, que estão em um ArrayCollection, para a Lista de telefones. Primeiro, para isso, vamos criar um evento personalizado, que vai carregar a lista de telefones com ele:

package events
{
	import flash.events.Event;

	import mx.collections.ArrayCollection;

	public class TelefoneEvent extends Event
	{
		public static const ATUALIZA_LISTA_TELEFONES_EVENT:String = "atualizaListaTelefones";

		public var telefones:ArrayCollection;

		public function TelefoneEvent(type:String, telefones:ArrayCollection)
		{
			super(type);
			this.telefones = telefones;
		}

		override public function clone():Event
		{
			return new TelefoneEvent(type, telefones);
		}

	}
}

Repare que declarei a constante com o tipo do evento dentro dele, para seguir o padrão dos outros eventos do Flex, e também a lista de telefones que esse evento vai transportar para o componente de Lista de Telefone.

Agora, no componente de Cadastro de Telefone, vamos declarar uma meta data de Event para que seja possível capturar esse evento no Application. Dessa maneira, o evento que fala que a lista precisa ser atualizada fica de responsabilidade do Cadastro de Telefones, e não no systemManager como você estava fazendo. No topo do componente de Cadastro de Telefone faça:

<mx:Metadata>
	[Event(name="atualizaListaTelefones", type="events.TelefoneEvent")]
</mx:Metadata>

E crie um método em um botão que vai disparar esse evento assim:

<mx:Script>
	<![CDATA[
		import events.TelefoneEvent;
		
		private var listaTelefones:ArrayCollection;
	
		private function atualizaLista():void
		{
			dispatchEvent(new TelefoneEvent(TelefoneEvent.ATUALIZA_LISTA_TELEFONES_EVENT, listaTelefones));
		}
	]]>
</mx:Script>

<mx:Button label="Atualiza lista" click="atualizaLista()"/>

Agora no seu Application, você vai escutar o evento “atualizaListaTelefones” assim:

<local:CadastroTelefones atualizaListaTelefones="onAtualizaListaTelefones(event)"/>

Agora crie o método “onAtualizaListaTelefones” no Application que vai receber o evento e fazer o que ele quer no componente de Lista de Telefones:

<mx:Script>
	<![CDATA[
		import events.TelefoneEvent;
		
		private function onAtualizaListaTelefones(event:TelefoneEvent):void
		{
			listaTelefones.atualiza(event.telefones);
		}
	]]>
</mx:Script>

<local:CadastroTelefones atualizaListaTelefones="onAtualizaListaTelefones(event)"/>
<local:ListaTelefones id="listaTelefones"/>

E na sua Lista de Telefones, você vai criar esse evento publico “atualiza” que recebe uma lista e mostra ela na tela.

Sobre a sua dúvida com o “bubbling” do event, ele faria com que o seu evento “subisse” vários níveis na hierarquia de componentes, até encontrar um listner adicionado em algum componente de nível mais alto.
Para entender melhor veja na documentação:

http://livedocs.adobe.com/flex/3/html/help.html?content=events_08.html

Espero ter esclarecido melhor suas dúvidas agora.

[]s

Ola,

     Sim, realmente esclareceu bem as minhas duvidas, hoje andei pesquisando bastante pelo assunto e vi algumas explicacoes muito boas tambem, muito obrigado! fico te devendo esta!

Abraços

André Martins