Arquitectura de Adobe Flex 2 (III)
- Publicado en: Componentes
- Escrito por Carlos Rovira
- 1 Comentario
- Enlace Permanente
Continuamos con nuestro recorrido a través del framework de Flex. En el último capÃtulo de esta serie comentamos las interioridades del framework para ver como funcionan las cosas “detrás de las cámaras” en Flex. En esta nueva entrega veremos como extender UIComponent para realizar nuestros propios componentes. El motivo de extender UIComponent es crear una pieza que encaje a la perfección dentro del ciclo de vida de nuestra aplicación y se beneficie de la infraestructura que nos da el framework de Flex. De esta forma conseguiremos un rendimiento óptimo.
La creación de componentes para Flex es un arte en si mismo y solo la experiencia y el estudio de otros componentes nos llevará a conseguir soluciones realmente interesantes. A su vez, es muy normal que en el dÃa a dÃa, desarrollando con Flex necesitemos alguna funcionalidad inexistente en los componentes base de Flex. Es en ese momento cuando necesitaremos de nuestros conocimientos de la arquitectura de Flex para solventar estos problemas creando nuestras propias extensiones.
Creando componentes a partir de UIComponent
A continuación podemos ver el mÃnimo código necesario para crear un componente en Flex:
[ftf w=”400″ h=”200″]
package com.mif.flexextension {
import mx.core.UIComponent;
public class NewComponent extends UIComponent {
public function NewComponent() {
super();
}
}
}
[/ftf]
Como podéis ver es bastante sencillo. Ahora bien, de esta forma solo crearÃamos un componente en blanco que no harÃa nada. Ni siquiera verÃamos nada en la pantalla. En el constructor podemos añadir escuchadores de eventos que sean necesarios en el componente. Por ejemplo UIComponent aprovecha el constructor para añadir escuchadores para el teclado o el manejador del foco.
Añadiendo objetos
Para empezar a añadir contenido al componente podemos hacerlo sobreescribiendo el método createChildren(). Por ejemplo, en el siguiente ejemplo comenzamos llamando al método del componente padre y posteriormente añadimos un campo de texto si este todavÃa no ha sido creado con anterioridad por alguna super clase:
[ftf w=”400″ h=”200″]
protected function createChildren():void {
super.createchildren();
if (!textField) {
textField = new UITextField();
textField.styleName = this;
addChild(textField);
}
}
[/ftf]
Este método será llamado por el framework de forma transparente al crear el componente. Es dentro de este método donde podemos crear cualquier sub componente o skin y añadirlo al displaylist del componente con addChild().
Tamaño de los componentes
Seguidamente, es tiempo de definir el método measure(), el cual se encargará de gestionar los tamaños del componente (tamaño mÃnimo, tamaño por defecto, …) y de los componentes hijos:
[ftf w=”400″ h=”200″]
override protected function measure():void {
super.measure();
measuredWidth = measuredMinWidth = 50;
measuredHeight = measuredMinHeight = 50;
}
[/ftf]
En el ejemplo indicamos que el tamaño base y mÃnimo deben ser de 50 pixeles tanto para el ancho como para el alto. Como vimos en el anterior artÃculo, siempre que queramos recalcular el tamaño del componente, llamaremos a invalidateSize(). NUNCA debemos de llamar directamente a este método. Otro método a tener en cuenta es setActualSize(), el cual se suele usar internamente para indicar el tamaño de los componentes hijos cuando se redibuja un componente.
Cambiando propiedades
El siguiente método es commitProperties(). Este se usa para modificar las propiedades de un componente. Gracias a este método nos aseguramos que los cambios en dichas propiedades se hacen en el orden y forma esperado por el programador. Lo normal es que cambiemos una propiedad dentro de un componente y, de paso, modifiquemos una variable flag de forma que en este método hagamos algún tipo de procesamiento necesario al cambiar la propiedad. El método de invalidación que debemos de usar para llamar a este método es invalidateProperties().
[ftf w=”400″ h=”200″]
// — propiedad que queremos cambiar
public function get label():String {
return _label;
}
public function set label(value:String):void {
// — Si el valor es distinto del que tenÃamos la propiedad cambia
if (_label != value) {
// — guardamos el valor en la propiedad interna del componente
_label = value;
// — marcamos la propiedad como cambiada
labelChanged = true;
// — El componente ha cambiado, por tanto invalidamos las partes necesarias. En este caso el tamaño y la visualización
invalidateSize();
invalidateDisplayList();
// — Despachamos un evento de cambio de la etiqueta para indicar a terceros componentes que existe un cambio en la propiedad label
dispatchEvent(new Event(“labelChanged”));
}
}
// — variable interna para guardar el valor de ‘label’
private var _label:String = “”;
// — Indicador o flag usado en el método commitProperties
private var labelChanged:Boolean = false;
protected function commitProperties():void {
if (labelChanged ) {
// — Realizar las operaciones necesarias y volver a poner el flag a false
labelChanged = false;
}
}
[/ftf]
Los flags nos permiten optimizar el rendimiento de este método de forma que solo se ejecuten determinadas partes del mismo. Este método es llamado justo antes de calcular el tamaño del componente y el redibujado del mismo. También es el lugar más apropiado para crear y eliminar subcomponentes de acuerdo con cambios determinados en las propiedades.
Visualizando el componente
Ha llegado el momento de visualizar el componente. Este es el método que tiene toda la carga de trabajo a la hora de representar gráficamente el estado del componente. Como cabrÃa de esperar, NO debemos de llamarlo directamente. Debemos de invocar invalidateDisplayList() de forma que marquemos el componente para su redibujado en el próximo frame.
[ftf w=”400″ h=”200″]
protected function updateDisplayList(unscaledWidth:Number,
unscaledHeight:Number):void {
super.updateDisplayList(unscaledWidth, unscaledHeight);
// — cada vez que llamemos a este metodo eliminamos lo que hubiese dibujado (con clear()
// — y dibujamos un rectangulo del tamaño del componente con el color indicado por el estilo “borderColor”
var g:Graphics = graphics;
g.clear();
g.lineStyle(1, getStyle(“borderColor”));
g.drawRect(0, 0, unscaledWidth, unscaledHeight);
}
[/ftf]
Como podéis ver en el ejemplo, primero llamamos al mismo método de la super clase. A partir de esta linea podemos usar este método para dibujar lo que creamos conveniente (en el ejemplo dibujamos un rectángulo), redimendionar sub componentes, cambiar estilos y, en general, todo lo que trate de cambiar la apariencia visual del componente.
Conclusión
Ahora ya tenemos la información básica suficiente para crear un componente desde cero. TodavÃa quedan otros aspectos a tener en cuenta (estilos, skinning, manejo del foco y del teclado, etc…). Pero en estos momentos ya sabemos cuales son los métodos que el framework de flex utiliza internamente para hacer su magia y podemos empezar a crear componentes que actúen dentro del sistema como si de un componente del framework se tratara.
En el siguiente artÃculo pondremos todo lo visto en práctica a través de un ejemplo con un componente real extendiendo de otro ya existente para reutilizar su funcionalidad. De esta forma podremos demostrar las ventajas de conocer la arquitectura de componentes de Flex y reutilizar la funcionalidad ya creada por los ingenieros de Adobe.
1 Comentario
Estoy desarrollando una aplicacion para almacenar y gestionar el conocimiento tanto con Adobe Flex como Adobe AIR; http://www.quesucede.com/page/show/id/polishedcode. La experiencia con Adobe Flex/AIR ha sido muy buena. Es una plataforma muy productiva.