好吧,这里有一个奇怪的错误。。。
在我的应用程序中,我加载了多个xml文件。为了加载这些,我总是创建一个新的URLLoader。没什么特别的。
第一个文件运行良好,第二个文件也运行良好。然而,第三个文件报告加载良好,但它所包含的数据实际上是第二个文件的数据。当前的解决方法是两次加载第三个文件,这在某种程度上起作用。。。奇怪的
我完全不知道这样的事情怎么会发生。当然,这三个文件都是具有不同路径的不同文件。
这是相关的类,希望它有任何用处,如果有什么不清楚的地方,请询问。DownloadJob类只是一个包含String和Function对象的辅助类。下载完成后会调用后一个。
// Actual class stuff
private var _downloadQueue :Array = new Array();
/**
* Adds a download to the queue. Will be started immediatly.
* @param p_url The URL of the download.
* @param p_callback The function to call when the download is finished. Has to take a DisplayObject/Sound/String as first parameter.
*/
public function addDownload(p_url:String, p_callback:Function) :void
{
var job :DownloadJob = new DownloadJob(p_url, p_callback);
_downloadQueue.push(job);
debug.ttrace("added: " + job.url);
// If it is the only item, start downloading
if (_downloadQueue.length == 1)
{
var job :DownloadJob = DownloadJob(_downloadQueue[0]);
load(job);
}
}
/**
* Will call the callback and dispatch an event if all loading is done.
* @param p_event The event that is passed when a download was completed.
*/
private function downloadComplete(p_event:Event) :void
{
var job :DownloadJob = DownloadJob(_downloadQueue[0]);
var downloaded :Object = p_event.target;
_downloadQueue.splice(0, 1);
debug.ttrace("completed: " + job.url);
// Notify via callback
if (downloaded is LoaderInfo)
{
job.callback(downloaded.content);
}
else if (downloaded is Sound)
{
job.callback(downloaded);
}
else if (downloaded is URLLoader)
{
// This one holds the data of the previously loaded xml, somehow
job.callback(URLLoader(downloaded).data);
}
// Continue downloading if anything is left in the queue
if (_downloadQueue.length > 0)
{
var job :DownloadJob = DownloadJob(_downloadQueue[0]);
load(job);
}
else
{
dispatchEvent(new Event(EVENT_DOWNLOADS_FINISHED));
}
}
/**
* Will load the passed job immediatly.
* @param p_job The job to load.
*/
private function load(p_job:DownloadJob) :void
{
// Different loaders needed for data, sound and non-sound
if (p_job.url.indexOf(".xml") != -1 ||
p_job.url.indexOf(".txt") != -1)
{
var urlloader :URLLoader = new URLLoader();
urlloader.addEventListener(Event.COMPLETE, downloadComplete);
urlloader.addEventListener(IOErrorEvent.IO_ERROR, handleError);
urlloader.load(new URLRequest(p_job.url));
}
else if ( p_job.url.indexOf(".mp3") != -1 &&
p_job.url.indexOf(".flv") != -1)
{
var sound :Sound = new Sound();
sound.addEventListener(Event.COMPLETE, downloadComplete);
sound.addEventListener(IOErrorEvent.IO_ERROR, handleError);
sound.load(new URLRequest(p_job.url));
}
else
{
var loader :Loader = new Loader();
loader.contentLoaderInfo.addEventListener(Event.COMPLETE, downloadComplete);
loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, handleError);
loader.load(new URLRequest(p_job.url));
}
}
}
我在你的类上花了一些时间,但找不到任何错误,即使是从计时器中随机调度addDownload
命令时也是如此——一切都如预期,没有混乱,没有奇怪的数据残留。我只能猜测,这个问题可能与ActionScript中奇怪的变量处理有关,如果它真的在你发布的代码中的话。
所以,我冒昧地重新安排了你们的班级:
- 我将队列的类型更改为
Vector.<DownloadJob>
。这让我们摆脱了所有的类型铸造 - 当前下载存储在字段变量
currentJob
中。无论如何,一次只能做一份工作。这就消除了所有的函数参数 - 如果
currentJob
不是null
,即实际正在进行下载,则只会将作业添加到队列中。如果不需要等待的话,我们不必排队。这只留下对每个push()
和splice()
的单个调用。在添加和删除内容方面不再存在不确定性 - 删除了匈牙利符号(我们在ActionScript中没有这样做)
- 将较大的方法拆分为更小、更可读的块(帮助我思考:)
- 删除了所有注释,除了API方法(我认为代码应该不言自明)
请尝试与您以前的类交换下面的代码,看看问题是否仍然存在。如果是这样,我确信问题存在于加载程序之外,可能存在于处理有效负载的回调函数中。
private static const EVENT_DOWNLOADS_FINISHED : String = "EVENT_DOWNLOADS_FINISHED";
private var currentJob : DownloadJob;
private var downloadQueue : Vector.<DownloadJob> = new Vector.<DownloadJob> ();
/**
* Adds a download to the queue. Will be started immediatly.
* @param url The URL of the download.
* @param callback The function to call when the download is finished. Has to take a DisplayObject/Sound/String as first parameter.
*/
public function addDownload ( url : String, callback : Function ) : void {
var job : DownloadJob = new DownloadJob ( url, callback );
if (currentJob) downloadQueue.push ( job );
else {
currentJob = job;
load ();
}
}
private function load () : void {
if ( jobIsText () ) loadText ();
else if ( jobIsSound () ) loadSound ();
}
private function jobIsText () : Boolean {
var url : String = currentJob.url;
return url.indexOf ( ".xml" ) != -1 || url.indexOf ( ".txt" ) != -1;
}
private function jobIsSound () : Boolean {
var url : String = currentJob.url;
return url.indexOf ( ".mp3" ) != -1;
}
private function loadText () : void {
var urlloader : URLLoader = new URLLoader ();
urlloader.addEventListener ( Event.COMPLETE, handleComplete );
urlloader.addEventListener ( IOErrorEvent.IO_ERROR, handleError );
urlloader.load ( new URLRequest ( currentJob.url ) );
}
private function loadSound () : void {
var sound : Sound = new Sound ();
sound.addEventListener ( Event.COMPLETE, handleComplete );
sound.addEventListener ( IOErrorEvent.IO_ERROR, handleError );
sound.load ( new URLRequest ( currentJob.url ) );
}
private function handleComplete ( ev : Event ) : void {
processPayload ( ev.target );
if (downloadQueue.length > 0) loadNext ();
else dispatchEvent ( new Event ( EVENT_DOWNLOADS_FINISHED ) );
}
private function handleError ( ev : Event ) : void {
trace ( "Error while downloading:" + currentJob.url );
}
private function processPayload ( loader : Object ) : void {
currentJob.callback ( getPayload ( loader ) );
currentJob = null;
}
private function loadNext () : void {
currentJob = downloadQueue.splice ( 0, 1 )[0];
load ();
}
private function getPayload ( loader : Object ) : Object {
return (loader is LoaderInfo) ? loader.content :
(loader is URLLoader) ? URLLoader ( loader ).data :
loader;
}