tutoriaux flash bibliotheques_de_fonctions
Vous êtes ici: Les articles techniques » tutoriaux » Tutoriaux et ressources Adobe Flash CS3 » Les bibliotheques dynamiquesLes bibliotheques dynamiques
Introduction
Vous l’avez sans doute remarqué, le code AS2 prend une place assez conséquente au chargement. Quelques classes et vous êtes rapidement sur des 30-40Ko au chargement.
Maintenant imaginez que vous avez plusieurs SWF qui utilisent des packages complexes (par exemple vous utilisez AS2Lib, XPath etc). Vous multipliez cette surcharge par autant de SWFs utilisés.
Il est possible de faire un préload sur un swf principal en exportant toutes les classes sur la deuxieme frame et en calculant le preload sur la premiere, mais ce n’est pas l’approche la plus propre.
Principe
Je vais lancer pas mal de trucs théoriques, ça pourrait être déroutant pour certains, et ce n’est pas fondamental pour savoir utiliser ces méthodes. La majorité d’entre vous devrait aller directement à la prochaine section.
Que se passe-t-il lorsque j’execute la commande suivante ?
import com.monsite.monappli.MaClasse; var instance:MaClasse = new MaClasse();
Et bien le compilateur va interpreter cela de la façon suivante :
if(!_global.MaClasse) { _global.MaClasse = new Function(){ code du constructeur }; var prot = MaClasse.prototype; ... } var instance:MaClasse = new MaClasse();
Qu’est-ce qu’il faut en retenir ?
- le code est interprété en AS1
- les classes sont créées en _global, donc accessibles de partout
Partant de cette constatation, avec un peu de jugeotte on se dit qu’un SWF chargé va créer ses classes dans _global de la même façon, et donc qu’elles seront fonctionnellement toutes accessibles après son chargement. C’est la dessus que repose le principe des bibliothèques de fonctions partagées.
En pratique
Nos acteurs
Nous allons travailler avec deux classes toutes bêtes à titre d’exemple :
- Class1
- org.aggelos.dll.Class2
class Class1 { function Class1() { trace("constructeur 1"); } function maFonction() { trace("maFonction 1"); } }
class org.aggelos.dll.Class2 { function Class2() { trace("constructeur 2"); } function maFonction() { trace("maFonction 2"); } }
Création de la librairie
L’idée est de faire un SWF dont le seul interêt est de forcer le chargement des classes. L’instruction
com.unsite.uneappli.UneClasse;
force l’inclusion de cette classe dans le script.
Attention ! notez qu’il n’y a pas le import et c’est chose voulue ! Lorsqu’on utilise la directive import, si la classe n’est jamais utilisée, elle n’est pas compilée !
Une bonne pratique pour charger toutes ses classes est de créer une classe ClassLoader comme suit :
class ClassLoader extends MovieClip { public function ClassLoader() { } public function doNothing() { Class1; org.aggelos.dll.Class2; } }
Il suffit donc ensuite de créer un fla, et sur la premiere image simplement mettre
(new ClassLoader()).doNothing();
Il suffit de compiler le swf en l’appelant malib.swf et on obtient de la sorte une librairie chargeable.
Chargement des librairies
Vous l’avez sans doute compris, une librairie se charge de la même façon que n’importe quel SWF. Toutefois, vous pouvez vous faire aider par des petites classes sympas comme le DLLLoader d’Aral BALKAN, qui se décompose en deux classes :
class com.ariaware.arp.utils.dll.DLLEvent { var type:String; var target:Object; var bytesLoaded:Number; var bytesTotal:Number; function DLLEvent ( type, bytesLoaded, bytesTotal ) { this.type = type; this.bytesLoaded = bytesLoaded; this.bytesTotal = bytesTotal; } }
import mx.events.EventDispatcher; import com.ariaware.arp.utils.dll.DLLEvent; class com.ariaware.arp.utils.dll.DLLLoader extends MovieClip { // On Stage var deadPreview:TextField; // Dynamically created clips var loaderShell:MovieClip = null; // // Group: Events broadcast // // Event: progress - On load progress (every frame) // Event: complete - When DLL has completely loaded // public function DLLLoader () { EventDispatcher.initialize ( this ); } //////////////////////////////////////////////////////////////////////////// // // Method: loadDll() // // Starts loading the specified DLL (SWF) file. A valid DLL file is a // SWF file that contains AS2 classes. // //////////////////////////////////////////////////////////////////////////// public function loadDll ( dll:String ) { // Create shell movie clip to load DLL into if it doesn't already exist if ( loaderShell == null ) { loaderShell = createEmptyMovieClip ( "loaderShell", getNextHighestDepth()); } // Load the movie loaderShell.loadMovie ( dll ); // Start the preloader onEnterFrame = preloader; } //////////////////////////////////////////////////////////////////////////// // // Group: Private methods // //////////////////////////////////////////////////////////////////////////// private function onLoad () { deadPreview._visible = false; } // Preloader method called every frame after DLL starts loading private function preloader () { var bytesLoaded:Number = getBytesLoaded(); var bytesTotal:Number = getBytesTotal(); if ( bytesLoaded == bytesTotal && bytesLoaded > 10 ) { // Ok, DLL has loaded -- wait a frame for it // to initialize so the classes become available. onEnterFrame = waitForInit; } else { dispatchEvent ( new DLLEvent ( "progress", bytesLoaded, bytesTotal ) ); } } // DLL has initialized. Broadcast the complete event private function waitForInit () { onEnterFrame = null; dispatchEvent ( new DLLEvent ( "complete", getBytesLoaded(), getBytesTotal() ) ); } // // Note: Methods to be mixed in by the EventDispatcher // function addEventListener(){}; function removeEventListener(){}; function dispatchEvent(){}; }
L’utilisation en est relativement simple (je vous la fais en simple, sans les Delegate):
import com.ariaware.arp.utils.dll.DLLLoader; import com.ariaware.arp.utils.dll.DLLEvent; var listener:Object = new Object(); listener.progress = function(evt) { //ici on a evt.bytesLoaded et evt.bytesTotal, impec pour un preload } listener.complete = function(evt) { //chargement fini, librairie initialisée } var loader:DLLLoader = new DLLLoader(); loader.addEventListener("progress",listener); loader.addEventListener("complete",listener);
Voila le principe, maintenant a vous de mettre des routines de chargement d’affilée etc.
Le typage
Voila l’aspect le plus complexe :) Probleme : je suis dans un swf dont je sais qu’il utilisera mes libraires et je veux
- typer
- mais ne pas charger mes fonctions
oui mais... les deux sont censément incompatibles vu que le typage implique le chargement ! Il y a deux remedes pour palier à ceci
Les fichiers d'exclusion
Il est possible de préciser des fichiers permettant d’exclure de la compilation certaines classes et uniquement ces classes là . Si elles utilisent à leur tour ces autres classes, ces classes ci seront compilées sauf instruction contraire.
Pour le compilateur flash
On utilise ce qu’on appelle un xml d’exclusion. Si votre fla s’appelle monFla.fla, il suffit de créer le fichier monFla_exclude.xml qui a la forme suivante :
<excludeAssets> <asset name="Class1" /> <asset name="org.aggelos.dll.Class2" /> </excludeAssets>
Ce fichier sera utilisé automatiquement !
Pour MTasc
Il suffit pour MTasc d’utiliser un fichier dont le contenu est une classe completement qualifiée par ligne, donc de la forme
Class1 org.aggelos.dll.Class2
et de taper simplement
mtasc vosfichiers.as... -exclude leFichierDexclusion
Les classes intrinseques
Vous etes vous déjà demandé à quoi servaient les classes déclarées en tant que
intrinsic class MaClass { }
?
Ce sont simplement des équivalent de fichiers “header” qui servent uniquement au typage pour le compilateur. Donc si au lieu de donner à votre fla un chemin qui pointe vers vos vraies classes vous lui donnez un chemin qui pointe vers des classes intrinseques equivalentes vous avez le typage sans la compilation. Dans notre cas de telles classes seraient ainsi :
intrinsic class Class1 { function maFonction(); } intrinsic class org.aggelos.dll.Class2 { function maFonction(); }
Attention aux dépendances toutefois ! Sinon vous aurez des conflits de typage :)
Au Secours ! Des outils !
Vous avez affaire à un problème plus complexe ? Comme par exemple un monstrueux paquet de dépendances par exemple parceque vous utilisez as2lib, xpath, remoting ? Merci OSFlash, qui héberge deux outils pour vous aider
Sexie
Bon, c’est mon petit cheri, forcément je l’ai crée de mes mains :p Sexie peut vous concevoir tout ce dont vous avez besoin : fichiers d’exclusion avec toutes les dépendances, et packages complets en intrinseque !
Comment l’utiliser ? Vous vous souvenez de notre classe ClassLoader ? Vous vous demandiez pourquoi elle heritait de MovieClip ? Simplement parceque nous allons en faire un composant :)
- ouvrez un fla vierge
- créez un clip vide dans la bibliotheque et cliquez sur le bouton droit
- dans le linkage liez le a ClassLoader
- dans definition de composant idem
- choisissez “exporter le fichier SWC”
- enregistrez votre compo
Alors oui, vous disposez de la possibilité de distribuer votre bibliotheque en tant que composant maintenant, ce qui est déjà pas mal. Mais maintenant ouvrez Sexie (ce qui necessitera une machine java 1.5). Dans l’invite du haut, allez chercher votre fichier swc et choisissez ce que vous voulez exporter. Tadaaaa, vous avez tout !
Sexie est dispo sur OSFlash
AsiGen
Asigen est un outil crée par Steve WEBSTER qui génère un package intrinseque à partir d’un package original. Ses atouts sont : * extreme facilité d’emploi * il ne regénère que les fichiers qui ont été modifiés * toutefois il génère tout le package, pas seulement les fichiers nécessaires.
Il est disponible lui aussi sur OSFlash
Le wiki a besoin de votre aide pour classer les pages.
Lorsque vous visitez une page, éditez la en rajoutant des tags ( catégories ) si la page n'en a pas, à l'aide la syntaxe suivante : {{tag>motClef1 motClef2 motClef3}}



