我使用开源库和自定义类的组合来处理这种情况。
对于加载,我主要使用
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 {
}
数据控制器有一些实例变量,例如这些:
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);
}
而 notify 函数看起来像这样:
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时,它将首先检查_processed中是否已设置$eventName数据。 如果有,则会将该数据传递给其订阅函数(在此情况下为_populate)。 如果尚未加载,则将订阅函数添加到_subscribers字典中,然后不执行任何其他操作。 当通过notify发送数据时,它将首先在_processed字典中设置数据,然后DataController将循环遍历$eventName的所有订阅者,并将数据传递给每个订阅函数。
还有我省略的方法可以让您做同样的事情,但不实际传递任何数据。 这些对于动画事件或链接任何其他类型的事件非常有用。
我还有删除订阅者和从_processed字典中删除数据的方法。
我希望这一切都说得通。
编辑
根据您的编辑,您可以像这样做:
在某个地方的代码,也许在您的文档类中。
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 {
}
private function _onBulkLoaderComplete($evt:Event):void {
DataController.instance.broadcast("ImagesComplete");
}
在只需要加载config.xml的情况下编写代码:
public function SomeClass():void {
DataController.instance.subscribe("configLoaded", _handleConfigLoaded);
}
private function _handleConfigLoaded($xml:XML):void {
}
使用这种方法,您的请求实际上是同步的。在加载config.xml之后,它会加载weather.xml。之后它会加载其他东西...等等。
您还可以使用BulkLoader加载5个内容,并监听每个内容的完成情况。根据需要触发通知和广播。