Flash AS3 - URLLoader снова загружает последние данные - PullRequest
0 голосов
/ 07 февраля 2012

Хорошо, вот одна странная ошибка ...

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

}

1 Ответ

1 голос
/ 07 февраля 2012

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