Adobe Flex: HowTo URLLoader [updated]

Auf der Suche wie man Dateien in Flex einlädt, findet man bei Adobe und anderen Seiten häufig folgendes Beispiel:

package {
import flash.display.Sprite;
import flash.events.*;
import flash.net.*;

public class URLLoaderExample extends Sprite {
public function URLLoaderExample() {
var loader:URLLoader = new URLLoader();
loader.addEventListener(Event.COMPLETE, completeHandler);
var request:URLRequest = new URLRequest(“urlLoaderExample.txt”);
try {
loader.load(request);
} catch (error:Error) {
trace(“Unable to load requested document.”);
}
}

private function completeHandler(event:Event):void {
var loader:URLLoader = URLLoader(event.target);
trace(“completeHandler: ” + loader.data);
}
// alle weiteren Handler gelöscht
}
}// Quelle www.adobe.com

Dies lädt schnell dazu ein, den Code-Schnipsel in den <mx:Script> Tag seiner MXML Datei zu kopieren, per initialize-Event oder creationComplete-Event diese Funktion aufzurufen und man hat sein Datenmodell in der ViewComponente drin. Funktioniert, aber schön ist das nicht!

Ich hätte das beinah auch so gemacht, wenn ich mein Modell nicht in zwei Views brauchen würde, und wenn ich nicht 10 XML Dateien als Modell hätte. Nach langem Suchen wurde ich in meinem Kopf fündig: in der C & OOP Klausur habe ich einem Objekt per Parameter Funktionen übergeben. Also habe ich folgende Storage Klasse geschrieben:
Und da meine erste Version einer kleinen DOS-Attacke glich, habe ich jetzt eine Warteschlange eingebaut, sodass die XML Dateien nacheinander geladen werden und nicht alle gleichzeitig…

package
{
import flash.events.*;
import flash.net.*;

import mx.collections.XMLListCollection;

public class Storage {
[Bindable] public var homeData:XMLListCollection = null;
[Bindable] public var newsData:XMLListCollection = null;

// URLLoader für alle
private var loader:URLLoader = null;

// Lade-Warteschlange
private var queue:Object = new Object();

// singleton
private static var storage:Storage = null;
public static function getInstance():Storage {
if ( storage == null ) storage = new Storage();
return storage;
}

public function loadHomeData(url:String):void {
if ( homeData == null )	load(url, this.setHomeData);
}

public function setHomeData(event:Event):void {
homeData = new XMLListCollection(new XMLList(event.target.data));
// loader Variable null setzen
loader = null;
// naechste Datei laden
loadNext();
}

public function loadNewsData(url:String):void {
if ( newsData == null ) load(url, this.setNewsData);
}
public function setNewsData(event:Event):void {
newsData = new XMLListCollection(new XML(event.target.data).children());
loader = null;
loadNext();
}

private function load(url:String, handlerObject:Function):void
{
// ueberpruefen ob die URL schon in der Warteschlange ist
if ( queue[url] == undefined )  {
queue[url] = {url: url, handlerObject : handlerObject};
}
// Ueberpruefen ob grade ein Ladevorgang aktiv ist
if ( loader == null )  {
loader = new URLLoader();
//configure Listeners
loader.addEventListener(Event.COMPLETE, handlerObject);
// load File
var request:URLRequest = new URLRequest(url);
try {
loader.load(request);
} catch (error:Error) {

trace(“Unable to load ‘” + url + “‘”);
}
}
}

private function loadNext():void {
// ersten Index aus der Warteschlange holen
for ( var i:String in queue ) {
break;
}
// Ueberpruefen ob ein gueltiges Element vorleigt
if ( queue[i] != undefined ) {
// Ladevorgang anstossen
load(queue[i]['url'], queue[i]['handlerObject']);
}
}
}

Nun rufe ich in den Views im initialize-Event

initialize="{Storage.getInstance().loadNewsData('news.xml')}"

auf und nutze das public Object newsData als dataProvider. Damit das ganze übersichtlicher bleibt habe ich mich hier nur auf das Complete Event beschränkt.

Ich habe die load Funktion extra gewrappt, damit ich bei Änderungen in der Storage Klasse nicht alle Views durchwuseln muss.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.