domenica 18 aprile 2010

[Actionscript 3] XMLLoader: Creare una classe che legga e prepari XML

In questo post tratterò di come creare una classe Actionscript 3 che carichi da se un file xml, semplicemente passandole un path, e a caricamenti avvenuto generi un evento ACTION da me definito.


Questa classe non fornisce metodi e proprietà per il parsing (navigazione/lettura/scrittura), dato che quanto fornito di default da AS3 mi sembrava più che sufficiente. Vien da sè che chiunque decida di reimplementarla migliorandola è ben accetto.


La classe è composta solo da poche righe, tuttavia avendo notato che sono praticamente sempre le stesse in qualsiasi progetto Flash, ho preferito raggrupparle tutte in una classe definita. Questo ha snellito i miei progetti e permesso di gestire meglio tutto il procersso di caricmaneto dati da XML.

package _classi{

import flash.events.*;
import flash.net.URLLoader;
import flash.net.URLRequest;
public class LoadXML extends EventDispatcher{
public static var ACTION:String = "action";
public var xmlData:XML = new XML();
public var objPath:String;
public var isLoaded:Boolean = false;
private var urlR:URLRequest=new URLRequest();
private var urlLoader:URLLoader = new URLLoader();

public function LoadXML(path) {
objPath = path;
urlR.url=objPath;
urlLoader.addEventListener(IOErrorEvent.IO_ERROR, errHandler);
urlLoader.addEventListener(Event.COMPLETE, xmlLoader);
urlLoader.load(urlR);
}
public function xmlLoader(e:Event = null):void {

xmlData=XML(urlLoader.data);
dispatchEvent(new Event(LoadXML.ACTION));
trace(xmlData.@src);
}

private function errHandler(e:IOErrorEvent):void {

trace("url errato");
trace(e.toString());
}

}
}

Innanzitutto definiamo il package (ossia la cartella all'interno della quale salvare la nostra classe. Io normalmente utilizzo "_classe", ma è ovvio che ognuno la definisce a suo piacimento e a seconda della sua posizione relativamente all'SWF che poi la utilizzerà.

Successivamente importiamo i package a noi necessari, quindi tutti gli eventi, il loader (colui che caricherà/conterrà fisicamente l'XML), l'URLRequest (che si occuperà di fornire al loader l'url da cui caricare).
package _classi{

import flash.events.*;


import flash.net.URLLoader;


import flash.net.URLRequest;
Ecco la prima nozuione interessante: definiamo la classe come estensione della EventDispatcher (traducibile all'incirca con 'Dispensatrice di Eventi').
Questa scelta è motivata dalla necessità di poter creare un evento proprio della classe che indichi quando l'XML è stato caricato. Eviteremo l'ingombro di dover definire ogni volta un ascoltatore dell'evento Event.COMPLETE nel nostro ipotetico SWF con tutti i relativi annessi e connessi (cosa fare se l'url dell'XML non esiste).
Ci basterà infatti definire nell'SWF target un ascoltatore all'evento ACTION, qui definito, senza preoccuparci di errori di url, che saranno tutti gestiti internamente alla classe.
public class LoadXML extends EventDispatcher{
public static var ACTION:String = "action";


public var xmlData:XML = new XML();//sarà il contenitore finale del nostro XML


public var objPath:String;//il path dell'XML


public var isLoaded:Boolean = false;//una variabile flag, che cambierà valore a caricamento ultimato


private var urlR:URLRequest=new URLRequest();//il contenitore dell'url dell'XML


private var urlLoader:URLLoader = new URLLoader();//il loader
Vediamo il costruttore. La prima azione che svolge è quella di associare assegnare alla proprietà url dell'oggetto URLRequest quanto passatogli nel parametro path. Assegnamo poi all'oggetto URLLoader (da non confondere con Loader) un ascoltatore che ci avvisi di eventuali errori nel url che andremo ad assegnargli e un ascoltatore che richiami la funzione xmlLoader, in caso l'url sia esatto, dell'avvenuto caricamento dei dati da XML.

Ora che tutti gli ascoltatori sono definiti, passiamo pure l'url all'oggetto URLLoader.
public function LoadXML(path) {
objPath = path;

urlR.url=objPath;


urlLoader.addEventListener(IOErrorEvent.IO_ERROR, errHandler);


urlLoader.addEventListener(Event.COMPLETE, xmlLoader);


urlLoader.load(urlR);
}
La funzione XMLLoader è quella che si occupa di 'travasare' i dati dall'URLLoader all'oggetto XML.

Ci si potrebbe chiedere come mai è necessario questo travaso, e perchè non far tutto con l'uno o con l'altro. Semplicemente perchè le proprietà/metodi dell'oggetto XML non sono sufficienti a caricare fisicamente i dati da file e le proprietà dell'oggetto URLLoader non sono sufficienti a gestire lalettura/navigazione dei dati una volta caricati. Dall'oltreonde, se così fosse, non avremo bisogno di implementare questa classe ;-)

Questo metodo viene richiamato a caricamento dati ultimato. Nella proprietà data dell'oggetto URLLoader avremo dunque, in sequenza binaria, il contenuto del nostro file XML. Da notare che ci saremo potuti appoggiare alla proprietà target dell'oggetto e, che tutti sappiamo puntare al 'target' dell'evento, e cioè urlLoader. O preferito tralasciare questa finezza per una maggiore chiareza del codice.

A questo punto utilizziamo il metodo dispatchEvent(), della classe EventDispatcher, che 'lancera' l'evento ACTION. Non abbiamo bisogno di instanziare un oggetto di questa classe per utilizzarla, in quanto ereditandola disponiamo gia adesso di tutti i suoi metodi/proprietà (esclusi i protected).

Questo metodo vuole come parametro l'oggetto Event che dall'esterno sarà il segnale che l'XML è stato caricato ed è pronto ad essere utilizzato. L'oggetto Event a sua volta vuole come parametro la stringa che lo identifica, notare che saràè la stessa proprietà statica che verrà utilizzata poi nell'ascoltatore che creeremo nell'SWF esterno.

Infine facciamo un trace del path dell'xml, a testimonianza che tutto è andato nel verso giusto.

public function xmlLoader(e:Event = null):void {

xmlData=XML(urlLoader.data);


dispatchEvent(new Event(LoadXML.ACTION));

trace(xmlData.@src);
}

Ora che la nostra classe, è completata, non ci resta che testarla all'interno di un qualsiasi SFW. Se tuttò va bene, otteremo un oggetto LoadXML la cui proprietà xmlData conterrà il nostro tanto agognato XML.

Spero di essere stato sufficientemente chiaro, buon lavoro a tutti in attesa del nostro prossimo tutorial! :D

Nessun commento:

Posta un commento