我结合使用开源库和自定义类来处理这种确切类型的情况。
对于加载,我主要使用BulkLoader,因为它会处理您想要加载的任何内容,并准备好监听所有事件。
我努力做的主要事情是让我的实现尽可能地解耦。因此,任何依赖数据的功能都通过订阅、通知设置来处理。我使用了一个名为 DataController 的自定义类。 DataController 是一个单例类,具有一些核心功能,包括:
subscribe, notify
假设我想加载一堆图像,但前提是我的包含图像路径的 XML 已完全加载
我会这样做:
在我的文档类或其他控制器类型类中,我会使用 BulkLoader 加载一些 XML。在完整的处理程序中,我会抓取 XML,比如 imageXML 并运行如下命令:
DataController.instance.notify("ImageXMLLoaded", imageXML);
在我的 ImageHolder 类中,我将拥有以下内容:
public function ImageHolder() {
DataController.instance.subscribe("ImageXMLLoaded", _populate);
}
private function _populate($imageXML:XML):void {
// do whaterver with your XML
}
DataController 有几个实例变量,如下所示:
private var _subscribers:Dictionary = new Dictionary(true);
private var _processed:Dictionary = new Dictionary(true);
private var _requests:Dictionary = new Dictionary(true);
订阅函数如下所示:
public function subscribe($eventName:String, $subscriber:Function): void {
var _funcArray:Array;
var _func:Function;
if (_processed[$eventName]) {
$subscriber(_processed[$eventName]);
return;
}
if (! _subscribers[$eventName]) {
_subscribers[$eventName] = new Array();
}
_subscribers[$eventName].push($subscriber);
}
通知函数如下所示:
public function notify($eventName:String, $data:*, $args:Object = null): void {
var _cnt:Number;
var _subscriberArray:Array;
var _func:Function;
_processed[$eventName] = $data;
if (_subscribers[$eventName] != undefined) {
_subscriberArray = _subscribers[$eventName].slice();
_cnt = 0;
while (_cnt < _subscriberArray.length) {
_func = _subscriberArray[_cnt] as Function;
if ($args) {
_func($feedXML, $args);
} else {
_func($feedXML);
}
_cnt++;
}
}
if (_requests[$eventName]) {
_subscriberArray = _requests[$eventName].slice();
delete _requests[$eventName];
_cnt = 0;
while (_cnt < _subscriberArray.length) {
if (_subscriberArray[_cnt] != null) {
_subscriberArray[_cnt]($data);
}
_cnt++;
}
}
}
还有我的请求函数:
public function request($eventName:String, $requestFunction:Function): void {
var _requestArray:Array;
var _request:Function;
if (! _feeds[$eventName]) {
if (! _requests[$eventName]) {
_requests[$eventName] = new Array();
}
_requests[$eventName].push($feedFunction);
} else {
$requestFunction(_feeds[$eventName]);
}
}
基本上,当您调用 subscribe 时,它会首先检查 $eventName 数据是否已在 _processed 中设置。如果有,它会将该数据传递给它的订阅函数(在这种情况下为 _populate)。如果它没有被加载,它会将订阅函数添加到 _subscribers 字典中,并且什么也不做。当通过 notify 发送数据时,会先在 _processed Dictionary 中设置,然后 DataController 会循环遍历并订阅 $eventName 并将数据传递给每个订阅函数。
还有一些我省略的方法可以让你做同样的事情,但实际上不传递任何数据。这些对于动画事件或将任何其他类型的事件链接在一起很有用。
我还有删除订阅者和从 _processed Dictionary 中删除数据的方法。
我希望这一切都有意义。
编辑
根据您的编辑,您可以执行以下操作:
代码某处,可能在您的文档类中。
public function startMyLoading():void {
loadConfig(onConfigLoaded);
}
public function onConfigLoaded($xml:XML):void {
DataController.instance.notify("configLoaded", $xml);
loadWeatherContiditons(onWeatherConditionsLoaded);
}
public function onWeatherConditionsLoaded($xml:XML):void {
DataController.instance.notify("weatherXMLLoaded", $xml);
}
在某处编码,也许是一些天气显示视图:
public function WeatherDisplayView():void {
DataController.instance.subscribe("weatherXMLLoaded", _populateWeatherPanel);
}
private function _populateWeatherPanel($xml:XML):void {
// for each (var weatherNode:XML in $xml.children()) ...
// use BulkLoader to load, and add Event.COMPLETE function for when it is finished.
}
private function _onBulkLoaderComplete($evt:Event):void {
DataController.instance.broadcast("ImagesComplete"); // the broadcast function is one that I did not include above, but basically works the same as subscribe, notify, but without any data being passed.
}
只需要加载 config.xml 的代码:
public function SomeClass():void {
DataController.instance.subscribe("configLoaded", _handleConfigLoaded);
}
private function _handleConfigLoaded($xml:XML):void {
// do something with config
}
使用这种方法,您的请求实际上是同步的。在加载 config.xml 后,它会加载 weather.xml。之后它会加载其他东西......等等等等。
您还可以使用 BulkLoader 加载您的 5 件事情,并听取每件事情的完成情况。根据需要触发通知和广播。