Apache Adobe Flex TutorialTutoriaux Adobe Flex & AIR en Français

17juin/110

AIR Mobile – Application Pokémon (11) – Affichage des statistiques / Création d'un composant

Dans le dernier tutorial, on a vu comment afficher une barre de statistiques dans notre application:

AIR Mobile – Application Pokémon (10) – Affichage des statistiques / Création de primitives

On a fait cela directement dans la vue pour le moment, pour s'entraîner. Sauf que par la suite, on va afficher plusieurs statistiques (attaque, défense, …). Comme on a pas envie de recopier ce code N fois, cela nous donne une bonne occasion pour créer un composant.

Vous avez déjà utilisé certains des composants disponibles dans le framework Flex (Image, View, Label, …). Ici, vous allez créer votre propre composant que vous allez ré-utiliser dans votre application. Cette pratique vous permet de factoriser le code afin de faciliter sa maintenance. Un peu comme lorsque l'on place un code répété plusieurs fois dans une fonction.

Création du composant

Rendez-vous dans la vue Package Explorer et sur le package "views", faites un click droit > New > MXML Component:

newc

Donnez lui le nom "PokemonStat". De base, pour un projet mobile, Flex remplit par défaut la valeur de "Based on" avec la classe View, ce qui vous permet de créer rapidement de nouvelles vues. Dans notre cas, on ne veut pas réaliser une nouvelle vue mais un composant que l'on va incorporer à notre View. Cliquez sur "Browse…". Une nouvelle fenêtre va s'ouvrir vous permettant de choisir la classe de base de ce composant. Dans notre cas, on va se baser sur VGroup. En effet, rappelez-vous de l'étape précédente, tous nos composants étaient encapsulés dans un conteneur de type VGroup.

Tapez "vg" pour que Flex vous suggère VGroup dans la liste et choisissez-là. Supprimez les valeurs de width / height par défaut:

com

Un nouveau fichier avec un squelette de code vient d'être créé pour vous:

<?xml version="1.0" encoding="utf-8"?>
<s:VGroup xmlns:fx="http://ns.adobe.com/mxml/2009"
          xmlns:s="library://ns.adobe.com/flex/spark">
  <fx:Declarations>
    <!-- Place non-visual elements (e.g., services, value objects) here -->
  </fx:Declarations>
</s:VGroup>

On va maintenant utiliser notre "esquisse" de composant que l'on a créé à l'étape 10 pour créer notre composant. N'oubliez pas le width="100%" à rajouter dans le tag racine:

<?xml version="1.0" encoding="utf-8"?>
<s:VGroup xmlns:fx="http://ns.adobe.com/mxml/2009"
          xmlns:s="library://ns.adobe.com/flex/spark" width="100%">
  <s:Label text="Attaque" color="white" />
  <s:Group width="100%" height="70">
    <s:Rect width="100%" height="100%">
      <s:fill>
        <s:SolidColor color="0xFF0000" />
      </s:fill>
      <s:stroke>
        <s:SolidColorStroke color="0x3E3E3E" weight="2" />
      </s:stroke>
    </s:Rect>
    <s:Rect width="100%" height="100%">
      <s:fill>
        <s:LinearGradient rotation="90">
          <s:GradientEntry color="0x000000" alpha="0" />
          <s:GradientEntry color="0x000000" alpha="0.4" ratio=".66" />
        </s:LinearGradient>
      </s:fill>
    </s:Rect>
    <s:Label fontSize="60" fontWeight="bold" color="0xEEEEEE" text="{_p.atk}" left="5"
             verticalCenter="0">
      <s:filters>
        <s:DropShadowFilter distance="1" angle="-90" color="0" blurX="0" blurY="0" />
      </s:filters>
    </s:Label>
  </s:Group>
</s:VGroup>

Si vous sauvegardez, vous n'obtiendrez aucune erreur. Pourtant, dans ce composant, nous référençons {_p.atk} qui ne correspond à rien dans ce contexte (dans le scope du composant). En fait, aucune erreur n'est générée car le composant n'est pas utilisé dans votre application. Il n'est donc pas compilé et le compilateur ne vous dira rien.

29mai/100

Flex 4 – (2) Création de composants Flex ré-utilisables, les meilleures techniques

La création de composants est un must quand on travaille avec Flex. Mais autant faut-il savoir les créer de la meilleures manière afin qu'ils puissent être ré-utilisés et faciliter la maintenance de votre code.

A ce propos, Tom Sugden a écrit un très bon article qui explique bien les meilleures manières pour faire un bon composant Flex:

Writing Genuinely Reusable Flex Components

Pour faire simple, je vais traduire cet article, et rajouter quelques commentaires et suggestions…

Pour de gros projets, en entreprise, on se retrouve souvent à extraire un ensemble de composants réutilisables dans un projet Flex Library. En théorie, les mêmes composants peuvent être utilisés dans plusieurs modules et/ou dans des applications Flex / Air. Cela permet d'avoir une base de code solide et facile à maintenir pour un développement plus rapide.

Cependant, dans la pratique, certaines erreurs de conception sont faites, qui limitent la ré-utilisabilité des composants. Cet article explique comment créer un composant totalement ré-utilisable et met en avant certaines techniques du SDK Flex qui peuvent être appliquées à vos propres composants.

Comment définir un composant "vraiment" réutilisable?

Il y a différents niveaux de ré-utilisabilité, mais un composant ré-utilisable devrait toujours pouvoir faire le rendu de n'importe quel type de donnée. Il devrait pouvoir fonctionner avec un tableau d'objets basiques (type Object) ou une collection d'objet de type Kangaroo par exemple.

Le composant Flex DataGrid permet de faire cela:

<mx:DataGrid dataProvider="{ kangaroos }">
 <mx:columns>
 <mx:DataGridColumn headerText="Name" dataField="name"/>
 <mx:DataGridColumn headerText="Weight" labelFunction="calculateWeight"/>
 </mx:columns>
</mx:DataGrid>

Notez que les propriétés "dataField" et "labelFunction" indiquent au composant comment récupérer sa donnée depuis les objets de type Kangaroo, sans imposer de dépendance. On a ici deux mécanismes possibles pour rendre un composant vraiment ré-utilisable. Même si le développeur n'as pas le contrôle sur la classe Kangaroo (si elle fait partie d'une librairie externe par exemple), il peuvent tout de même être rendu dans une DataGrid.

L'Anti-Pattern Data Interface

Une des erreurs courantes est d'obliger la donnée qui va être rendue par un composant à implémenter une interface spécifique. Par exemple, on va prendre le composant DistributionBar qui fait le rendu d'un graphique comme celui-ci:

DistributionBar

On affiche un certain nombre de régions de tailles différentes, chacune contenant un label. Il est tentant de configurer ce composant pour qu'il utilise un tableau d'objet IRegion:

public interface IRegion
{
 function get label() : String;
 function get size() : int;
}

Le composant pourra ensuite extraire les informations de taille et de label pour chaque région par cette interface. L'argument en faveur de cette démarche est que l'interface découple le composant de l'objet concret qui est rendu. N'importe quel objet peut être rendu tant qu'il implémente IRegion, mais c'est dans le "tant que" que réside la faille de conception.

En imposant l'utilisation de l'interface IRegion, la ré-utilisabilité du composant est limitée. L'interface doit être implémentée par les classes du Model avant de pouvoir être rendue par le composant. Encore pire, si vos models sont produits par une autre librairie (dont vous pouvez ne pas avoir les sources) ou par une autre équipe, il se peut que vous ne puissiez pas changer les classes, elles devront donc être "wrappées" (encapsulées dans d'autres objets qui implémentent IRegion).

Pour ces raisons, le composant n'est pas vraiment ré-utilisable.

Notez que cette considération est importante pour les composants qui doivent être complètement ré-utilisables comme les DataGrid ou les List Flex. Pour des composants plus "métiers" ou le fait de pouvoir instancier son composant sans configurer trop de propriétés, on pourra utiliser le "pattern Data Interface". Parfois, il vaut mieux passer du temps à créer un composant qui soit ré-utilisable mais parfois il est plus aisé/rapide de créer plusieurs composants (par héritage) pour des besoins métiers spécifiques.

Les composants ré-utilisables du SDK Flex

Le SDK Flex contient de nombreux composants ré-utilisables, utilisant plusieurs approches:

  1. Data Fields
  2. Data Functions
  3. Data Descriptor
  4. Factory Objects

Ces approches et ces techniques peuvent être appliquées à vos propres composants pour les rendre ré-utilisables.

20juin/0814

Composant Flex – Image avec barre de chargement intégrée

Le composant Flex <mx:Image> permet d'importer des fichiers JPEG, PNG, GIF, et SWF à l'exécution. Vous pouvez aussi embarquer ces fichiers à la compilation en utilisant @Embed(source='nomFichierImage').

Les images embarquées sont chargées immédiatement, car elles font déjà partie du fichier Flex SWF. Cependant, elle font augmenter la taille du SWF et vous devez recompiler à chaque modification.

L'alternative à cela est de charger les ressources à l'exécution. Vous pouvez charger une ressource depuis le système de fichiers local là où la SWF est situé ou y accéder depuis une ressource distante (par HTTP typiquement).

Cependant, le temps que l'image se charge, une espace transparent est affiché sans donner à l'utilisateur d'information sur la progression du téléchargement de l'image.