martes, 20 de mayo de 2008

Problema Integrando Flex y Flash (eventos del mismo tipo con clases distintas)

En el proyecto en que me encuentro laborando actualmente me salio uno de los errores mas raros que he visto.

Sintomas

1. Tenia un componente hecho en flash (swc) incluido en una clase de Flex.
2. El componente en flash despachaba un evento customizado y la clase en Flex no tenia ningun problema con el evento customizado.
3. Cuando interactuaba con el componente que se cerraba o se abria conforme se necesitara, recibia el siguiente evento:

TypeError: Error #1034: Type Coercion failed: cannot convert fl.events::ComponentEvent@dc0f4c1 to mx.events.FlexEvent.
at flash.events::EventDispatcher/dispatchEventFunction()
at flash.events::EventDispatcher/dispatchEvent()
at fl.core::UIComponent/set visible()

El error es que se estaba intentando convertir un evento de tipo fl.core.UIComponent a un evento de tipo FlexEvent. Pero... el evento que teniamos conocimiento que despachaba el componente era de una clase distinta. Ademas revisando el codigo del componente cuando veiamos el error, no se estaba despachando ningun tipo de evento desde el componente.

Despues de revisar muchas veces el codigo, nos dimos cuenta que el problema se daba cuando al componente se le hacia visible=false.
Entonces se nos encendio el bombillo y nos pusimos a revisar la documentacion del ComponentEvent y del FlexEvent .

Problema

Al componente Flash hacer visible=false, se despachaba el evento ComponentEvent.HIDE cuyo tipo es "hide" y si se hacia visible=true despachaba un evento ComponentEvent.SHOW de tipo "show". Coincidentemente la clase FlexEvent tiene los tipos de eventos SHOW de tipo "show" y HIDE de tipo "hide". Como pueden observar tienen el mismo nombre. Pero al mismo tiempo nuestro contenedor en Flex tenia listeners para SHOW y HIDE pero de FlexEvent y al tener el mismo tipo o nombre, esos listeners en el Flex iban a ser invocados. Lo que sucede es que los listeners esperaban eventos de tipo FlexEvent y no de ComponentEvent.

Solucion

Agregue listeners directamente al componente para los eventos ComponentEvent.HIDE y ComponentEvent.SHOW e inmediatamente pare su propagacion (event.stopPropagation) para que no llegaran hasta el Flex, osea el contenedor del componente.

Moraleja

Para aplicaciones que vayan a usar componentes Flash en Flex:

1. Se debe programar a la defensiva.. es decir buscar prevenir cualquier situacion en la que algo del Flash API nos pueda dar conflicto con algo del Flex Framework sea un evento, una clase, etc.
2. Cuando se hagan eventos customizados debemos tratar de diferenciar los tipos de ellos lo mas posible, talvez anadiendo el nombre del paquete donde se encuentran.

En fin.. espero que de alguna forma pueda servirle a alguien..