Руководство по actionscript. часть 6, стр. 018

RemoveChild(progressOutput);

}

}

}

Почему бы не использовать событие Event. OPEN? Если вы просматривали документацию по API среды выполнения Flash, то, возможно, обратили внимание на кажущееся удобным событие Event. OPEN, которое возникает в момент начала загрузки. Теоретически событие Event. OPEN предоставляет хорошее место, где можно размещать код для добавления индикатора хода выполнения в список отображения. Как мы уже знаем, код, отображающий ход выполнения, выполняет четыре основные задачи.

1. Создание индикатора хода выполнения.

2. Добавление индикатора хода выполнения в список отображения.

3. Обновление индикатора хода выполнения.

4. Удаление индикатора хода выполнения из списка отображения.

Первая операция обычно выполняется на этапе подготовки. Три оставшиеся операции соответствуют трем событиям загрузки: Event. OPEN, Event. PROGRESS и Event. COMPLETE. Вы можете поинтересоваться, почему же класс SunsetViewer из листинга 28.7 добавляет объект progressOutput в список отображения в методе load ( ), а не в приемнике события Event. OPEN.

Руководство по actionscript. часть 6, стр. 019

Private function load (url Request.-URLRequest) :void { loader. load(urlRequest); if (lcontains(progressOutput)) {

// Почему мы делаем это здесь…

addChild(progressOutput);

private function openListener (e:Event):void { if (!contains(progressOutput)) { // …а не здесь? addChild(progressOutput);

}

}

На самом деле приемник события Event. OPEN теоретически мог бы быть прекрасным местом для добавления объекта progressOutput в список отображения. К сожалению, на практике специфическое поведение браузеров затрудняет использование события Event. OPEN, и поэтому в данной книге мы избегаем его применения. Исчерпывающую информацию по этому вопросу можно найти далее, в подразд. «Аспекты поведения при ошибках загрузки, зависящие от среды».

Мы уже знаем, как загружать внешний элемент, отображать его на экране и показывать ход выполнения его загрузки пользователю. Теперь рассмотрим код, необходимый для восстановления работоспособности программы после ошибок загрузки.

Обработка ошибок загрузки

Как мы уже знаем из гл. 19, всякий раз, когда попытка загрузить элемент терпит неудачу из-за ограничений безопасности, приложение Flash Player либо генерирует исключение SecurityError, либо выполняет диспетчеризацию события SecurityErrorEvent. SECURITY_ERROR. Всякий раз, когда такая попытка терпит неудачу по любой другой причине, среда выполнения Flash осуществляет диспетчеризацию события IOErrorEvent. IO_ERROR, получателем которого является объект Loaderlnfo элемента. Обрабатывая это событие, мы можем попытаться восстановить работоспособность программы после любой ошибки загрузки, не связанной с ограничениями безопасности. Например, в приемнике события IOErrorEvent. IO_ERROR мы могли бы написать код, который просит пользователя проверить подключение к Интернету.

Руководство по actionscript. часть 6, стр. 020

Добавим код, обрабатывающий ошибки загрузки, в наш класс SunsetViewer. Чтобы зарегистрировать приемник для получения уведомлений о возникновении событий IOErrorEvent. I0_ERR0R, мы используем уже знакомый код:

1oader. contentLoaderInfо. addEventLi stener(IOErrorEvent. I0_ERR0R,

ioErrorListener);

Здесь ioErrorListener — ссылка на функцию, которая будет обрабатывать данное событие. В следующем коде представлена функция ioErrorListener. В нашем приложении SunsetViewer функция ioErrorListener ( ) просто отображает сообщение об ошибке пользователю в текстовом поле progressOutput.

// Приемник вызывается при возникновении ошибки загрузки private function ioErrorListener (е:IOErrorEvent):void { progressOutput. text = «LOAD ERROR»:

}

В отличие от других событий загрузки, если при диспетчеризации приложением Flash Player события IOErrorEvent. IO ERROR, получателем которого является

объект Loaderlnfo, никакая функция-приемник не зарегистрирована для его обработки, среда выполнения Flash генерирует ошибку на этапе выполнения. Например:

Error #2044: Unhandled IOErrorEvent:. text=Error #2035: URL Not Found.

Безусловно, сообщение об ошибке Unhandled IOErrorEvent (Необработанное событие IOErrorEvent), как и обо всех ошибках на этапе выполнения, отображается только в отладочной версии приложения Flash Player. В рабочей версии приложения Flash Player среда Flash не выдаст пользователю никаких сообщений об ошибках загрузки. Вместо этого она полагает, что реагировать на ошибки соответствующим образом должен код приложения.

Руководство по actionscript. часть 6, стр. 021

В листинге 28.8 представлена окончательная версия класса SunsetViewer, дополненная кодом для обработки ошибок загрузки. Новый код выделен полужирным шрифтом.

Листинг 28.8. Окончательная версия класса SunsetViewer, с обработкой ошибок загрузки

package { import flash. display.*: import flash. net. URLRequest; import flash. events.* import flash. text.*;

public class SunsetViewer extends Sprite { private var loadenLoader; private var progressOutput:TextField;

public function SunsetViewer ( ) { createLoader( ); createProgressIndicator( ); load(new URLRequest(«sunset. jpg»));

}

private function createLoader ( ):void { loader = new Loader( );

1oader. contentLoaderlnfо. addEventLi stener(ProgressEvent. PROGRESS,

progressListener);

1oader. contentLoaderlnfо. addEventLi stener(Event. COMPLETE,

completeListener);

1oader. contentLoaderlnfo. addEventListener(Event. INIT,

initListener);

1oader. contentLoaderlnfо. addEventLi stener(IOErrorEvent. I0 ERR0R,

ioErrorListener);

}

private function createProgressIndicator ( ):void { progressOutput = new TextField( ); progressOutput. autoSi ze = TextFi eldAutoSi ze. LEFT; progressOutput. border = true; progressOutput. background = true; progressOutput. selectable = false;

progressOutput. text = «LOADING…»;

}

private function load (urlRequest:URLRequest):void { loader. load(urlRequest); if (lcontains(progressOutput)) { addChild(progressOutput);

}

}

private function progressListener (e:ProgressEvent):void { progressOutput. text = «LOADING: «

+ Math. floor(e. bytesLoaded / 1024)

+ 7″ + Math, fl oor (e. bytesTotal / 1024) + » KB»;

}

private function initListener (e:Event):void { addChi1d(1oader. content);

}

private function completeListener (e:Event):void { removeChild(progressOutput);

}

// Приемник вызывается при возникновении ошибки загрузки private function ioErrorListener. (е:IOErrorEvent):void { progressOutput. text = «LOAD ERROR»;

}

}

}

Аспекты поведения при ошибках загрузки, зависящие от среды

При осуществлении операций загрузки среда выполнения Flash полагается на свою локальную среду (то есть на операционную систему или приложение, в котором запускается среда выполнения Flash, — зачастую таким приложением является браузер). Как результат, некоторые аспекты поведения Flash, связанного с загрузкой данных, зависят от среды. Среда выполнения по мере возможности пытается оградить программиста от подобных аспектов поведения. Тем не менее в приложении Flash Player 9 существуют два аспекта поведения, которые представлены в табл. 28.1, — они являются уникальными для приложения Internet Explorer в операционной системе Windows и требуют особого внимания программиста.

Руководство по actionscript. часть 6, стр. 022

Таблица 28.1. Аспекты связанного с загрузкой поведения приложения Internet Explorer

Особенность Поведение Internet Explorer Поведение автономного проигрывателя, приложений firefox и Adobe AIR

Event. OPEN Все операции загрузки генерируют событие Event. OPEN, даже если в дальнейшем они завершатся неудачей по причине «файл не найден» Событие Event. OPEN не генерируется для операций загрузки, которые завершаются неудачей по причине «файл не найден»

Особенность Поведение Internet Explorer Поведение автономного проигрывателя, приложений firefox и Adobe AIR

Переменная экземпляра text класса IOErrorEvent Когда загрузка завершается неудачей по причине «файл не найден», переменной text присваивается значение «Еггог #2036: Load Never Completed* (Загрузка не будет завершена) Когда загрузка завершается неудачей по причине «файл не найден», переменной text присваивается значение Error #2035: URL Not Found (Адрес URL не найден)

Ни одно из описанных в табл. 28.1 поведений не является «правильным». Каждое поведение просто зависит от среды, под управлением которой запущена среда Flash. Тем не менее, поскольку согласованность между поведениями всех сред отсутствует, необходимо проявлять осторожность при написании кода, который использует событие Event. OPEN или переменную экземпляра text класса IOErrorEvent. Чтобы добиться платформенной независимости, выполняйте две следующие рекомендации.

? Не используйте значение переменной экземпляра text класса IOErrorEvent для принятия решений в логике ветвления. Используйте эту переменную только для отладочных целей.

? Избегайте применения события Event. OPEN для любых целей, кроме отладки.

Рассмотрим один пример, который объясняет, почему использование события Event. OPEN может вызвать проблемы в приложении. Предположим, что приложение использует пользовательский класс LoadBar для отображения хода выполнения операции загрузки. Приложение добавляет экземпляр класса LoadBar в список отображения всякий раз, когда начинается операция загрузки, внутри приемника события Event. OPEN:

private function openListener (e:Event):void { addChild(loadBar):

}

Теперь предположим, что приложение пытается загрузить файл, который не может быть найден. Если приложение будет запущено в браузере Internet Explorer, метод openListener ( ) выполнится и экземпляр класса LoadBar появится на экране. Однако если приложение будет запущено в любом другом браузере, метод openListener ( ) не выполнится и экземпляр класса LoadBar не появится на экране. В лучшем случае разработчик заметит данное несоответствие и напишет код для браузера Internet Explorer, удаляющий экземпляр класса LoadBar с экрана в случае ошибки загрузки. Подобный код усложняет приложение и увеличивает вероятность появления ошибок. В худшем случае разработчик не заметит данное несоответствие и в Internet Explorer экземпляр класса LoadBar будет находиться на экране в течение всего жизненного цикла приложения.

Руководство по actionscript. часть 6, стр. 023

Чтобы полностью избежать подобной проблемы, безопаснее всего вообще не использовать событие Event. OPEN. Вместо этого просто применяйте методику, которая была рассмотрена в коде из листинга 28.7: добавляйте на экран любые индикаторы хода загрузки вручную перед началом загрузки.

В будущих версиях языка ActionScript аспекты поведения, зависящие от среды, которые были перечислены в табл. 28.1, возможно, будут стандартизованы, и вам больше не придется избегать использования события Event. OPEN.

Отладка с использованием класса HTTPStatusEvent

Когда HTTP-клиент запрашивает некий элемент по протоколу HTTP, HTTP-сервер возвращает код статуса, который сообщает о том, как был обработан данный запрос. Например, если HTTP-запрос был обработан успешно, HTTP-сервер вернет код статуса 200. Если обработка HTTP-запроса завершилась неудачно, сервер отправит статус ошибки, описывающий возникшую проблему. Коды статуса HTTP для ошибок загрузки зачастую представляют более подробную информацию, чем общее событие IOErrorEvent. IO_ERROR языка ActionScript, поэтому эти коды полезно использовать при отладке. Однако поддержка кодов статуса HTTP реализована не во всех средах.

Версии приложения Flash Player, реализованные в виде модулей расширения браузеров Netscape, Mozilla (Firefox), Safari, Opera и Internet Explorer (версия для операционной системы Macintosh), не поддерживают коды статуса HTTP.

При получении кода статуса HTTP от сервера приложение Flash Player осуществляет диспетчеризацию события HTTPStatusEvent. HTTP_STATUS, получателем которого является объект Loaderlnfo загружаемого элемента. Чтобы зарегистрировать приемник для получения уведомлений о возникновении события HTTPStatusEvent. HTTP_STATUS, мы используем следующий код:

oObeKTLoader. contentLoaderInfo. addEventLi stener(HTTPStatusEvent. HTTP_STATUS,

httpStatusListener);

Здесь oObeKTLoader — объект Loader, загружающий элемент, a httpStatusL istener — ссылка на функцию, которая будет обрабатывать данное событие. В функцию httpStatusLi stener передается объект HTTPStatusEvent, переменная status которого содержит код статуса HTTP. Следующий код демонстрирует типовую функцию httpStatusL istener. Обратите внимание на способ получения кода статуса HTTP из объекта HTTPStatusEvent е:

private function httpStatusListener (e:HTTPStatusEvent):void { traceC’http status: » + e. status):

}

Как бы удивительно это ни звучало, фактически приложение Flash Player осуществляет диспетчеризацию события HTTPStatusEvent. HTTP_STATUS для каждой отдельной операции загрузки, даже если не получает код статуса HTTP от сервера. В тех случаях, когда никакой код статуса HTTP не получен, переменной экземпляра status класса HTTPStatusEvent присваивается значение 0. Например, во всех следующих ситуациях переменной status присваивается значение 0:

? файл загружается локально или из некоторого источника не по протоколу HTTP;

? сервер HTTP недоступен;

? запрашиваемый URL-адрес указан неправильно;

? коды статуса HTTP не поддерживаются средой (например, приложение Flash Player выполняется в браузере Mozilla Firefox).

Руководство по actionscript. часть 6, стр. 024

Мы рассмотрели все общие вопросы, относящиеся к загрузке отображаемых элементов на этапе выполнения с помощью объекта Loader. В следующих разделах рассматриваются вопросы, касающиеся использования загруженных SWF-файлов.

Проверка типов на этапе компиляции для динамически загружаемых элементов

Ранее из подразд. «Обращение к загруженному элементу» разд. «Использование класса Loader для загрузки отображаемых элементов на этапе выполнения» мы узнали, что переменная экземпляра content класса Loader ссылается на объект, представляющий загруженный элемент. Мы также узнали, что в зависимости от типа загруженного элемента переменная content может ссылаться либо на экземпляр класса Bitmap, либо на экземпляр основного класса SWF-файла. Экземпляры этих несопоставимых классов допускается присваивать переменной content, поскольку ее типом данных является DisplayOb j ect, а класс Bitmap и все основные классы SWF-файлов наследуются от класса DisplayOb j ect. Как результат, любым объектом, присвоенным переменной content, можно управлять с помощью переменных и методов класса DisplayOb j ect, но над ним нельзя вызывать более специфические переменные и методы класса Bitmap или основного класса SWF-файла.

Например, с помощью следующего кода допустимо обратиться к переменной экземпляра width класса DisplayObject объекта, на который ссылается переменная

content:

// Класс DisplayObject определяет переменную width, // поэтому ошибки не будет loader. content. width

Следующий код подобным образом пытается обратиться к переменной экземпляра bitmapData класса Bitmap объекта, на который ссылается переменная content. Однако на этот раз данный код вызывает ошибку компиляции, поскольку в классе DisplayOb j ect не определена переменная bitmapData.

ОШИБКА: «Access of possibly undefined property bitmapData through a reference with static type flash. display:DisplayObject.» (Обращение к возможно неопределенному свойству bitmapData через ссылку на статический класс flash. display:Di splayObject)

1oader. content. bi tmapData. getPi xel(0, 0)

Чтобы избежать ошибок на этапе компиляции при обращении к методам и переменным класса Bitmap через переменную content, мы приводим ее значение к типу Bitmap, как показано в следующем коде:

Bitmapdoader. content) .bitmapData. getPixel (1, 1) ;

Операция приведения типов сообщает компилятору, что загруженный элемент является экземпляром класса Bitmap, в котором определена переменная bitmapData.

Руководство по actionscript. часть 6, стр. 025

Подобным образом при использовании методов и переменных класса MovieClip над загруженным SWF-файлом мы приводим значение переменной content к типу MovieCl ip. Например, следующий код начинает воспроизведение гипотетической анимации путем вызова метода экземпляра play ( ) miaccaMovieClip над загруженным элементом. Операция приведения типов (обязательная) сообщает компилятору, что загруженный элемент является потомком класса MovieCl ip и, следовательно, поддерживает метод play ( ).

MovieClip(loader. content).play( );

Точно так же, когда используются пользовательские методы и переменные основного класса загруженного SWF-файла, вполне естественно ожидать, что значение переменной content приводится к этому основному классу. Предположим, что приложение Main. swf загружает другое приложение Module. swf, основным классом которого является класс Module. Предположим также, что класс Module определяет собственный метод start ( ). Когда приложение Ma in. swf загружает приложение Module. swf, среда выполнения Flash автоматически создает экземпляр класса Module и присваивает его переменной content. Таким образом, чтобы вызвать метод start ( ) над загруженным экземпляром класса Module, можно предположить, что необходимо использовать следующую операцию приведения типов:

Module(loader. content).start( );

Хотя, по существу, предыдущий код корректен, фактически он будет вызывать ошибку на этапе компиляции до тех пор, пока не будут приняты особые меры при компиляции файла Main. swf. Рассмотрим почему.

Предположим, что приложения Ma in. swf и Module, swf созданы в виде отдельных проектов в приложении Flex Builder 2. Эти два проекта созданы с учетом того, что приложения должны быть автономными и независимыми, поэтому в них используется совершенно разный код и они никак не ссылаются друг на друга. В проекте приложения Module. swf определяется класс Module, однако приложение Main. swf ничего не знает про этот класс. При построении файла Main, swf компилятор встречает следующий код:

Module(loader. content).start( )

и не может разрешить ссылку на класс Module, используя пути, указанные для свойства ActionScript Build Path (Путь компиляции ActionScript) приложения Main. swf. Не найдя класс Module, компилятор предполагает, что выражение Module (loader. content) является вызовом метода. Однако метода с именем Module не существует, поэтому компилятор генерирует следующую ошибку типа:

1180: Call to a possibly undefined method Module.

По-русски она будет звучать так: Вызов, возможно, неопределенного метода Module.

Руководство по actionscript. часть 6, стр. 026

Существует два способа решения данной проблемы: мы можем отключить проверку типов на этапе компиляции или предоставить компилятору доступ к классу Module при компиляции файла Main. swf. Эти способы рассматриваются в двух следующих разделах.

Отключение проверки типов на этапе компиляции

Чтобы отключить проверку типов на этапе компиляции при применении пользовательских методов и переменных основного класса загруженного SWF-файла, мы можем привести значение переменной loader. content к типу данных Ob j ect, как показано в следующем коде:

Object(loader. content).start( ); // Ошибки компиляции не будет

Кроме того, можно присвоить то значение, на которое ссылается переменная loader. content, нетипизированной переменной:

var module:* = 1oader. content:

module. start( ): // Ошибки компиляции не будет

В качестве альтернативы мы можем обратиться к загруженному объекту с помощью выражения событие In 11. target. content из функции-приемника события Event. INIT. Проверки типа значения переменной экземпляра target класса Event на этапе компиляции не происходит, поскольку типом данных объекта target является Object.

private function initListener (e:Event):void { e. target. content. start( ): // Ошибки компиляции не будет

}

В каждом из перечисленных случаев компилятор не генерирует ошибку при обращении к методу start ( ). Вместо этого проверка типа нашего значения переменной loader. content откладывается до этапа выполнения. Тем не менее, как мы уже знаем из гл. 8, отключение проверки типов на этапе компиляции приводит к потере производительности. В тех случаях, когда проверка типов откладывается до этапа выполнения, сообщения об ошибках не появятся, пока не будет выполнен потенциальный проблемный код, поэтому время отладки увеличивается.

Руководство по actionscript. часть 6, стр. 027

Чтобы избежать увеличения времени отладки, мы можем предоставить компилятору доступ к классу Module при компиляции приложения Main. swf. Этот процесс подробно описан в следующем разделе.

Предоставление компилятору доступа к загружаемому классу

Чтобы избежать ошибок компиляции при приведении значения переменной loader. content к основному классу загружаемого SWF-файла, мы можем предоставить компилятору языка ActionScript доступ к этому классу на этапе компиляции. Для этого существуют три различные методики: путей исходных файлов, путей библиотек и путей внешних библиотек. Каждая из перечисленных методик рассматривается в трех следующих разделах на примере класса Module из предыдущего раздела. В каждом случае компилятору предоставляется доступ к классу Module при компиляции приложения Main. swf.

Три методики, рассматриваемые в следующих разделах, подходят для различных ситуаций. Используйте методику путей исходных файлов в том случае, когда верны оба следующих утверждения:

? допускается увеличение общего размера файлов приложения;

? вы хотите сделать так, чтобы исходный код загружаемого SWF-файла (в нашем примере Module. swf) был непосредственно доступен автору приложения, из которого происходит обращение к этому SWF-файлу (Main. swf в нашем примере).

Используйте методику путей библиотек, когда допускается увеличение общего размера файлов приложения и когда верно одно из следующих утверждений:

? вы не хотите, чтобы исходный код загружаемого SWF-файла был непосредственно доступен автору приложения, из которого происходит обращение к этому SWF-файлу;

? время, необходимое для компиляции SWF-файла, к которому происходит обращение, должно быть минимизировано.

Используйте методику путей внешних библиотек, когда увеличение размера файла всего приложения не допускается.



Полезные ссылки
Случайные записи
  • 11.05.2010">Самоучитель по креативному веб-дизайну. Книга 1, стр.46
  • 12.08.2010">Как подают информацию о владельце, команде
  • 11.03.2011">Руководство по actionscript. часть 3, стр. 149
  • 17.11.2011">Обзор SandyBridge E
  • 04.10.2010">Создание анимации в Photoshop
  • 01.03.2011">Руководство по actionscript. часть 5, стр. 111
  • 15.06.2010">Самоучитель по креативному веб-дизайну. Книга 4, стр.53
  • 03.11.2011">Как создать кинопостер
  • 17.06.2010">Самоучитель по креативному веб-дизайну. Книга 4, стр.12
  • 21.06.2011">Как правильно оптимизировать сайт для социальных сетей
  • 16.03.2011">Руководство по actionscript. часть 3, стр. 030
  • 23.05.2012">Machinima привлекла инвестиций на $35 миллионов благодаря Google
  • 18.05.2010">Самоучитель по креативному веб-дизайну. Книга 2, стр.42
  • 09.05.2010">Самоучитель по креативному веб-дизайну. Книга 1, стр.135
  • 17.03.2011">Руководство по actionscript. часть 2, стр. 140
Опрос

Какие цвета вы предпочитаете?

View Results

Loading ... Loading ...