2012-02-07 2 views
0

Хорошо, вот одна странная ошибка ...Вспышка AS3 - URLLoader загружает последние данные снова

В моем приложении, я загрузить несколько файлов 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)); 
     } 
    } 

} 
+0

Хорошо, я узнал, что он работает, если я НЕ использую новый URLLoader каждый раз. Когда я использую один и тот же URLLoader для всех моих запросов, ошибка исчезла. Это обходное решение, с которым я могу жить. ... ... Тем не менее, ошибка меня смущает. Должна быть какая-то ошибка памяти во Flash. – TheSHEEEP

+1

Прежде всего, ваша строка, в которой вы проверяете, является ли файл FLV или MP3 неправильным. Ваше условное выражение && not ||. Во-вторых, я не уверен, что вы можете загрузить FLV в класс Sound, но я могу ошибаться.В-третьих, вы можете публиковать ВСЕ код, так как этот код ничего не показывает, кроме того, как вы загружаете, когда реальная проблема вполне может исходить из вашего поколения URL-адресов, которое вы передаете addDownload. –

+0

Спасибо за звуковой подсказку, понял, что звук может загружать только mp3 некоторое время назад, но забыл удалить это из класса. Как показывает мой вышеприведенный комментарий, работа с URL-адресом работает правильно. – TheSHEEEP

ответ

1

Я провел некоторое время на классе и не смогли найти каких-либо ошибок, даже посылая случайные 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; 
} 
+0

Это на самом деле невозможно, так как класс загружает только один элемент за раз. Всегда первый. И отладчик показывает, что все элементы загружаются по порядку. – TheSHEEEP

+0

Вы были правы - на самом деле, ваш код работал очень хорошо для меня ... Во всяком случае, я отредактировал свой ответ. Посмотрите, поможет ли это найти проблему. – weltraumpirat

+0

Эй, вы серьезно приложили много усилий в это! .... и превратил мой хороший прокомментированный и стилизованный код в ... этот материал;) Действительно, мне пришлось смеяться над «мы не делаем этого в ActionScript»: D ... Если вы посмотрите на комментарии выше , Я уже нашел обходное решение, используя один единственный URLLoader. Но так как вы прилагаете такое усилие, чтобы помочь мне, я тоже попробую сделать это и отчитаться :) – TheSHEEEP

Смежные вопросы