¿Quieres registrarte?

Comunicación entre módulos cargados con ModuleLoader en Flex

Por: Zguillez
31 de Octubre del 2008

En este tip mostraré como comunicarse con módulos cargados dentro de una película Flex principal. Los módulos son pequeñas películas MXML que creamos para luego incorporar dentro de otro MXML principal, de igual manera que un componente pero en este caso se genera un archivo .SWF externo independiente, lo que resulta útil ya que podemos compartir módulos entre diferentes películas.

Para colocar un módulo dentro de una película principal existen dos opciones, y con una nos encontraremos un pequeño problema al intentar comunicarnos.

La primera forma es como si de un componente se tratase, osea definiríamos el namespace, por ejemplo, xmlns:modules="*", y lo colocaríamos con ese tag:

Código :

<modules:module id="modulo"/>


Si este módulo tuviese una función actionscript pública llamada setTexto(t:String); que le asignase el valor a una variable privada podríamos acceder a ella sin problema desde la película MXML principal.

Código :

private function setModuleText():void
{
   modulo.setTexto("texto")
}


Ahora bien, también podríamos haber cargado el módulo con el componente ModuleLoader. De esta manera hubiésemos enlazado directamente al archivo .SWF generado al publicar el módulo:

Código :

<mx:ModuleLoader id="modulo" url="module.swf"/>


Cargarlo de esta manera es útil ya que nos permite intercambiar un modulo por otro dentro del mismo componente reasignando el parámetro URL. Al enlazar directamente al SWF nos permite incorporar módulos generados desde otras películas, incluso desde otros servidores.

El problema es que al colocar el módulo con ModuleLoader nos saltará un error al intentar acceder a sus funciones públicas.

Error :

1061: Llamada a un método setTexto posiblemente no definido mediante una referencia con tipo estático mx.modules:ModuleLoader.


¿Cómo lo podemos solucionar? Deberemos hacer que ese módulo implemente una Interface que disponga de esa función pública a la que queremos acceder.

Crearíamos esta sencillo archivo de interface, al que llamaríamos IModule.as:

Código :

package
{
   public interface IModule
   {
      function setTexto(t:String):void
   }
}


Para hacer que el módulo implemente esta interface le incluiremos el parámetro en el tag de definición:

Código :

<mx:Module xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" implements="IModule">


Y de esta manera deberemos asignar la definición de tipo a la instancia del módulo para llamar a la función que implementa la interface:

Código :

private function setModuleText():void
{
   var mod:IModule = modulo.child as IModule;
   mod.setTexto("texto");
} 


Ahora si tenemos acceso a las funciones públicas del módulo :)

Este es todo el código completo por si alguien quiere darle un vistazo:

module.mxml

Código :

<?xml version="1.0" encoding="utf-8"?>
<mx:Module xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" implements="IModule">   
   <mx:Script>
      <![CDATA[
         [Bindable]
         private var _texto:String;
         
         public function setTexto(t:String):void
         {
            _texto = t;
         }   
      ]]>
   </mx:Script>   
   <mx:Label verticalCenter="0" left="20" right="20" textAlign="center" id="textoInput" text="{_texto}"/>   
</mx:Module>


Main.mxml

Código :

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:modules="*"   layout="absolute">
   <mx:Script>
      <![CDATA[
         private function setModuleText1():void
         {
            modulo1.setTexto("texto1")
         } 
         private function setModuleText2():void
         {
            var mod:IModule = modulo2.child as IModule;
            mod.setTexto("texto2");
         } 
      ]]>
   </mx:Script>
   <mx:VBox horizontalCenter="0" verticalCenter="0" horizontalAlign="center">   
      <modules:module id="modulo1"/>
      <mx:ModuleLoader id="modulo2" url="module.swf"/>      
      <mx:Button label="Button1" click="setModuleText1()"/>
      <mx:Button label="Button2" click="setModuleText2()"/>      
   </mx:VBox>   
</mx:Application>


IModule.as

Código :

package
{
   public interface IModule
   {
      function setTexto(t:String):void
   }
}

Enviar a twitter Enviar a facebook


También te interesa


Etiquetas flex actionscript_3 mxml comunicacion modular

Comentarios | Enviar un comentario
¿Y ese problema existe también en las variables públicas?

¿Habría que definirlas en la interface con getters y setters?
Por: Zah
muy buen tip y necesario además.. mejora el rendimiento en las aplicaciones y hace reutilizables nuestros modulos, alguna vez vi un ejemplo de esta implementación http://www.presenciaeninternet.es/?p=90
Por: vanvanero
me queda la duda si hay que definir en la Interface todos los metodos y propiedades que quiero reutilizar no sería algo complicado en ese sentido?
Por: vanvanero

Zah-blog :

¿Y ese problema existe también en las variables públicas?

¿Habría que definirlas en la interface con getters y setters?

Si, también con los settes y getters... Todo a lo que quieras acceder a de estar definido en la interface
Por: Zguillez

vanvanero-blog :

me queda la duda si hay que definir en la Interface todos los metodos y propiedades que quiero reutilizar no sería algo complicado en ese sentido?

Más que complicado es más estricto.. ya que estas obligado a definir la interface publica del modulo aunque eso te hará tener los módulos más claros y más reutilizables..
Por: Zguillez
Perfecto!, he leido mucho sobre esto y ahora si me ha quedado claro :) . Gracias Z .
Por: Otaku RzO
No me queda del todo claro, ya que lo estoy implementando en mi aplicacion y no funciona.

Yo tengo una aplicacion que funciona como shell, está me carga los modulos mediante un componente ModuleLoader pero estos componentes son .swf, cuando hago la declaracion de la interfaz IModule:

var mod:IModule = modulo2.child as IModule;
mod.setTexto("texto2");

me genera un error ya que no la declaro en ningúna parte, los .swf los estoy generando como proyectos independientes a mi shell, por lo tanto no tengo la interfaz por ningun lado y si me dá por pegar el archivo en mi proyecto aunque no genera error no me funciona, que estaré haciendo mal??.
Por: ingjuanfelipe
Deja un comentario
IMPORTANTE

Recuerda ser respetuoso, no insultes a otras personas, ni uses palabrotas, hay una persona al otro lado de la pantalla.

Habla bien, NO ESCRIBAS EN MAYUSCULA TODO, no escribas como en un SMS, evita cosas como "ke", "x q" y demás abreviaciones.

Aquí funcionan las etiquetas de los foros, puedes usar [b] para negrita, [img] para las imágenes, [url] para los enlaces, etc.

Si tienes preguntas técnicas, envíalas mejor al foro.