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

Чтобы собрать небольшие сегменты данных в одно целое, клиент должен вручную добавлять каждый сегмент во временный массив байтов (то есть в «буфер байтов») по мере загрузки этого целого. «Целым» может быть файл, объект, готовая инструкция, почтовое сообщение, сообщение чата или любая другая логическая структура данных, которая должна обрабатываться как единый элемент. Всякий раз, когда появляется новый сегмент, клиент проверяет, не завершена ли загрузка всего целого. Если да, то клиент приступает к его обработке. Если нет, то клиент ожидает появления дополнительных данных.

Стоит отметить, однако, что не существует официального способа проверить, было ли полностью получено некоторое логическое тело данных. Каждый бинарный сокетный протокол предоставляет свои собственные механизмы, позволяющие определить момент завершения текущей передачи данных. Например, сервер может сообщить своему клиенту, сколько данных будет передано до начала следующей передачи, или клиент может проверять загружаемую последовательность байтов на наличие маркеров начала и конца файла. В нашем примере клиент будет приступать к обработке загруженного отображаемого элемента сразу после закрытия сокетного соединения сервером. Закрытие сокетного соединения — это (очень простой) способ сообщить нашему клиенту о завершении отправки данных некоторого элемента.

Посмотрим, как все это будет выглядеть в коде. Наш простой клиент, написанный на ActionScript, состоит из одного класса DisplayAssetLoader. Чтобы получить и отобразить элемент, отправляемый сервером FileSender, класс DisplayAssetLoader должен выполнить такую последовательность действий.

1. Создать объект Socket.

2. Зарегистрировать объект DisplayAssetLoader для событий объекта Socket.

3. Использовать объект Socket для подключения к серверу.

4. Когда через сокет будут получены новые бинарные данные, поместить эти данные во временный буфер.

5. Когда сокет отсоединится, использовать метод экземпляра loadBytes ( ) класса Loader, для того чтобы загрузить бинарные данные из временного буфера в объект Loader.

6. Отобразить объект загруженного элемента на экране.

В листинге 28.13 представлен весь код целиком для класса DisplayAssetLoader. Ключевые возможности класса DisplayAssetLoader обсуждаются после листинга; незначительные детали описываются в виде комментариев к коду.

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

Листинг 28.13. Класс DisplayAssetLoader

package { import flash. display.*; import flash. events.*; import flash. net.*; import flash. text.*; import flash. utils.*;

public class DisplayAssetLoader extends Sprite { // Константа, представляющая ASCII-символ // «завершение передачи» public static const EOT:int = 4; // Объект TextField, отображаемый на экране, // в который выводятся // статусные сообщения private var statusField.-TextField;

// Объект сокета, через который будет устанавливаться соединение private var socket:Socket;

// Буфер байтов, в который по мере загрузки будут помещаться бинарные // данные элемента

private var buffer:ByteArray = new ByteArray( );

// Объект Loader, используемый для генерации элемента из загруженных

// бинарных данных

private var loader:Loader;

// Конструктор класса

public function DisplayAssetLoader ( ) {

// Создаем объект TextField для отображения статусных сообщений

statusField = new TextField( );

statusField. border = true;

statusField. background = true;

statusField. width = statusField. height = 350;

addChild(statusField);

// Создаем объект сокета socket = new Socket( );

// Регистрируем приемники для событий сокета socket. addEventLi stener(Event. CONNECT, connectListener); socket. addEventLi stener(Event. CLOSE, closeLi stener); socket. addEventLi stener(ProgressEvent. S0CKETJ3ATA,

socketDataListener); socket. addEventListener(IOErrorEvent.10 ERROR, ioErrorListener);

// Сообщаем пользователю, что сейчас мы попытаемся подключиться // к сокету

out(«Attempting connection…»);

// Пытаемся подключиться к сокету try {

socket. connectClocalhost». 3000): } catch (e:Error) { outC’Connection problem!\n»); out(e. message):

}

// Обрабатывает события подключения к сокету private function connectListener (e:Event):void { out(«Connected! Waiting for data…»);

}

// Обрабатывает вновь полученные данные private function socketDataListener (e:ProgressEvent):void { out(«New socket data arrived.»);

// Когда появляются новые байты, помещаем их в буфер для дальнейшей // обработки

socket. readBytes(buffer, buffer. length, socket. bytesAvai1able);

}

// Обрабатывает события отключения сокета. Когда происходит отключение, // пытаемся сгенерировать отображаемый элемент из загруженных байтов, private function closeListener (e:Event):void {

// Сначала проверяем, был ли получен весь элемент целиком…

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

// Обращаемся к последнему байту в буфере

buffer. position = buffer. length — 1;

var lastByte;int = buffer. readUnsignedByte( );

// Если байт «завершение передачи» отсутствует,

// значит, бинарные данные элемента загружены не полностью,

// поэтому элемент не создаем

if (lastByte!= DisplayAssetLoader. EOT) { return;

}

// Все в порядке, мы можем благополучно сгенерировать элемент из // загруженных байтов. Последний байт в буфере не является частью // элемента, поэтому отбрасываем его. buffer. length = buffer. length — 1;

// Теперь создаем объект Loader, который сгенерирует элемент // из загруженных байтов loader = new Loader( );

// Генерируем элемент из загруженных байтов 1oader.1oadBytes(buffer);

// Ожидаем завершения процесса инициализации элемента 1oader. contentLoaderlnfo. addEventLi stener(Event. INIT,

assetlnitListener);

}

// Помещает элемент на экран после завершения процесса его инициализации private function assetlnitListener (e:Event):void {

addChi1d(1oader. content);

outCAsset initialized.»);

}

// Обрабатывает ошибки ввода/вывода private function ioErrorListener (e:IOErrorEvent):void { out(«I/0 Error: » + e. text);

}

// Выводит статусные сообщения на экран и на отладочную консоль private function out (msg:*):void { trace(msg);

statusField. appendText(msg + «\n»);

}

}

}

Рассмотрим три основные части класса DisplayAssetLoader: создание и подключение к сокету, помещение байтов в буфер и создание отображаемого элемента из загруженных байтов.

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

Создание и подключение к сокету

Для установки сокетного соединения и управления им мы используем экземпляр класса Socket, который присваиваем закрытой переменной socket:

socket = new Socket( );

Чтобы подключиться к сокету, мы используем метод экземпляра connect ( ) класса Socket. Однако поскольку сокетные соединения потенциально могут генерировать ошибки безопасности и ошибки ввода/вывода, мы помещаем вызов метода connect ( ) в блок try/catch:

try {

socket. connectC’localhost», 3000); } catch (e:Error) { out(«Connection problem!\n»); out(e. message);

}

Помещение байтов в буфер

Как мы уже знаем, при получении новых данных через сокет среда Flash выполняет диспетчеризацию события ProgressEvent. SOCKET_DATA. Получателем данного события является объект Socket, получивший эти данные. Таким образом, чтобы получать уведомления о появлении новых данных, мы регистрируем в объекте socket приемник для события ProgressEvent. SOCKET_DATA, как показано в следующем коде:

socket. addEventLi stener(ProgressEvent. SOCKET_DATA. socketDataLi stener);

Всякий раз, когда возникает событие ProgressEvent. SOCKET_DATA, вызывается метод экземпляра socketDataListener ( ) класса DisplayAssetLoader. Внутри метода s о eke t Da taLi stener ( ) переменная экземпляра byte s Avail able класса Socket обозначает количество байтов в сокете, доступных для чтения на настоящий момент. Метод socketDataListener ( ) добавляет новые полученные данные в объект ByteArray, на который ссылается переменная buffer. Чтобы прочитать новые данные и сохранить их в объекте buffer, мы используем метод экземпляра readBytes ( ) класса Socket, который принимает следующий общий вид:

o6beKTSocket. rea6Bytes(6aiiTbi, смещение, длина)

Здесь объектБоскеЬ — это объект Socket, из которого будут прочитаны байты, байты — объект ByteArray, в который будут записаны байты, смещение — позиция внутри объекта байты, с которой начнется запись, а длина — количество байтов, которое будет прочитано из сокета. В нашем случае мы хотим прочитать все байты из сокета и сохранить их в объекте buffer, начиная с конца объекта buffer. Следовательно, мы используем такой код:

socket. readBytes(buffer, buffer. length, socket. bytesAvai1able);

Рассмотрим полный листинг кода для метода socketDataListener ( ):

private function socketDataListener (e:ProgressEvent):void { out(«New socket data arrived.»);

socket. readBytes(buffer, buffer. length, socket. bytesAvai1able);

}

Создание отображаемого элемента из загруженных байтов

Как только все байты для элемента будут получены, мы можем использовать метод экземпляра loadBytes ( ) класса Loader для создания из этих байтов экземпляра класса DisplayObject языка ActionScript. Напомним, что сервер FileSender сообщает о завершении передачи данных в полном объеме путем простого закрытия сокетного соединения. Поэтому мы помещаем код, создающий наш экземпляр класса DisplayOb j ect («объект элемента»), в приемник события Event. CLOSE. Чтобы зарегистрировать приемник для события Event. CLOSE в объекте socket, мы используем следующий код:

socket. addEventLi stener(Event. CLOSE, closeLi stener);

Вфункции closeListener ( ) перед созданием экземпляра класса DisplayObject мы сначала проверяем, был ли получен байт «завершение передачи» (ASCII-код 4) от сервера. Напомним, что сервер отправляет байт «завершение передачи» в качестве последнего байта потока данных. Чтобы получить этот байт, мы используем следующий код:

buffer. position = buffer. length — 1;

var lastByte:int = buffer. readUnsignedByte( );

Если байт «завершение передачи» отсутствует, бинарные данные элемента были получены не полностью, и поэтому функция-приемник завершает свое выполнение:

if (lastByte!= DisplayAssetLoader. EOT) { return;

Если байт «завершение передачи» был получен, мы создаем объект элемента с помощью метода loadBytes ( ). Тем не менее перед передачей байтов элемента в метод loadBytes ( ) мы должны сначала удалить байт «завершение передачи» из буфера, как показано в следующем коде:

buffer. length = buffer. length — 1:

Теперь, имея на руках байты элемента, мы можем создать объект элемента:

loader = new Loader( ): 1oader.1oadBytes(buffer):

После завершения выполнения предыдущего кода запускается процесс генерации объекта элемента, однако сам объект элемента пока недоступен. Как и в случае с методом экземпляра load ( ) класса Loader, если попытаться обратиться к объекту элемента через переменную loader. content сразу после вызова метода loadBytes ( ), будет возвращено значение null. Таким образом, перед тем как обратиться к объекту элемента, мы должны дождаться возникновения события Event. INIT:

loader. contentLoaderInfo. addEventListener(Event. INIT.

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

AssetlnitListener);

Когда элемент станет доступен, мы добавляем его на экран:

private function assetlnitListener (e:Event):void { addChi1d( 1 oader. content): outC’Asset initialzed.»):

}

Напомним, что при возникновении события Event. INIT становятся доступными элементы и объекты, созданные в конструкторе основного класса SWF-файла или в коде, который размещается в первом кадре временной шкалы SWF-файла, но при этом элементы и объекты, создаваемые во втором и последующих кадрах,, недоступны. Дополнительные сведения об обращении к визуальным элементам и объектам, создаваемым во втором и последующих кадрах, можно найти ранее в разд. «Обращение к элементам в многокадровых SWF-файлах».

Удаление SWF-элементов, загруженных на этапе выполнения

Чтобы удалить из приложения SWF-элемент, загруженный на этапе выполнения, мы должны сначала обнулить все ссылки на него в приложении, а затем либо обнулить все ссылки на объект Loader, загрузивший этот элемент, либо вызвать метод unload ( ) над данным объектом Loader.

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

Обычные задачи, необходимые для деактивации загруженного SWF-файла, распределяются между приложением, загрузившим этот элемент, и самим элементом.

Приложение, загрузившее элемент, перед удалением этого элемента должно выполнить следующее.

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

? Если загрузка элемента еще не завершена, приложение должно прекратить операцию загрузки. Например:

try {

theAssetLoader. closet );

}

catch (e:*) {}

? При обнулении всех ссылок на элемент приложение должно удалить элемент из всех родительских экземпляров объекта DisplayObjectContainer. Например:

container. removeChild(theAsset); Сам элемент перед удалением должен выполнить следующие задачи.

? Сообщить любым загруженным дочерним SWF-элементам о необходимости деактивации.

? Остановить воспроизведение любых звуковых файлов.

? Остановить воспроизведение основной временной шкалы, если ее воспроизведение происходит в настоящий момент.

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

? Остановить воспроизведение любых клипов, проигрываемых в настоящий момент.

? Закрыть любые подключенные сетевые объекты, например экземпляры классов

Loader, URLLoader, Socket, XMLSocket, LocalConnect ion, NetConnections HNetStream.

? Обнулить все ссылки на объекты Camera или Microphone.

? Отменить регистрацию всех приемников событий (особенно это касается события Event. ENTER_FRAME, а также приемников событий мыши и клавиатуры).

? Остановить все интервалы, выполняющиеся в настоящий момент (с помощью метода clearlnterval ( )).

? Остановить все объекты Timer (с помощью метода экземпляра stop ( ) класса Timer).

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

За дополнительной информацией о деактивации элементов перед их удалением обратитесь к разд. «Деактивация объектов» гл. 14. Кроме того, прочитайте серию интернет-статей Гранта Скиннера (Grant Skinner) под названием «ActionScript 3.0: Resource Management, опубликованных по адресу http://www. gskinner. com/blog/ archives/2006/06/as3_resource_ma. html.

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

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

Встраивание отображаемых элементов на этапе компиляции

Чтобы включить внешний отображаемый элемент в приложение, написанное на языке ActionScript, на этапе компиляции, мы используем тег метаданных [ Embed ]. Этот тег добавляет указанный внешний элемент в SWF-файл и делает этот элемент доступным для программы в виде определенного пользователем или автоматически сгенерированного класса. Экземпляры встроенного элемента создаются из этого класса с помощью стандартного синтаксиса оператора new языка ActionScript.

I Тег метаданных [Embed] поддерживается приложением Flex Builder 2 и консольным & 4 * компилятором mxmlc. Однако тег метаданных [Embed] не поддерживается приложением flft Adobe Flash CS3. Возможно, поддержка тега [Embed] появится в будущих версиях среды разработки Flash.

Для использования тега [Embed] мы должны предоставить компилятору доступ к библиотеке flex, swc, поддерживающей компилятор Flex. По умолчанию все проекты, создаваемые в приложении Flex Builder 2, автоматически включают библиотеку flex. s wc в пути библиотек языка ActionScript, поэтому в приложении Flex Builder 2 методики, рассматриваемые в данном разделе, будут работать без каких-либо специальных настроек компилятора.

Замечание по размеру файла и потреблению памяти

В отличие от методик загрузки элементов на этапе выполнения, рассмотренных в этой главе, встраивание отображаемого элемента на этапе компиляции с помощью тега метаданных [Embed] увеличивает размер SWF-файла, загружающего этот элемент, а также увеличивает объем используемой средой выполнения Flash памяти. По этой причине встраивать элемент на этапе компиляции необходимо только в том случае, когда вы абсолютно уверены в том, что приложению обязательно понадобится этот элемент. В противном случае загружать данный элемент следует на этапе выполнения по мере необходимости.

Например, представьте приложение, которое является электронным каталогом продукции с изображениями тысячи товаров и одним изображением экрана приветствия. Изображение экрана приветствия выводится при каждом запуске приложения, и, следовательно, его целесообразно встроить с помощью тега метаданных [ Embed]. В отличие от этого, изображение товара необходимо только в том случае, когда пользователь просматривает нужный товар, и, следовательно, оно должно загружаться на этапе выполнения и удаляться, когда пользователь завершит просмотр этого товара.

Теперь, когда мы узнали, в каких случаях применяется тег [Embed], посмотрим, как использовать его на практике. В следующем разделе рассматривается обобщенный код, необходимый для использования тега [ Embed ]. В последующих разделах приведены конкретные примеры использования обобщенного кода, рассматриваемого в следующем разделе.

Обобщенный синтаксис тега [Embed]

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

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

Следующий код демонстрирует типовое использование тега [Embed] на уровне определения переменной:

[Embed (source="путьКФайлу") ] private var ИмяКласса:C1ass;

При компиляции данного кода компилятор языка ActionScript автоматически генерирует новый класс, представляющий внешний элемент, местоположение которого определяется значением путьКФайлу, и присваивает этот класс закрытой переменной с именем ИмяКласса. Суперклассом нового класса является один из классов в пространстве имен mx. core, предназначенных для встраивания элементов. Как мы увидим в последующих разделах, выбор конкретного класса-прослойки зависит от типа встраиваемого элемента. Значение путьКФайлу должно определять местоположение файла элемента с помощью одного из следующих способов:

? абсолютной ссылки, предоставляющей компилятору доступ к элементу на локальном компьютере (например, с: /assets/photo. jpg);

? относительной ссылки, сформированной по отношению к исходному файлу на языке ActionScript, из которого происходит встраивание элемента (например, . . /images/photo. jpg).

Стоит отметить, что, поскольку переменная ИмяКласса ссылается на класс, ее типом данных является Class. Когда переменная ссылается на объект Class, первая буква в имени этой переменной обычно записывается в верхнем регистре (в соответствии с общепринятым стилем именования классов).

Установив связь между встраиваемым элементом и переменной ИмяКласса, мы используем следующий знакомый нам код для создания нового экземпляра элемента.

new ИмяКласса( );

Теперь вернемся к обобщенному синтаксису для использования тега метаданных [Embed] на уровне определения класса. Следующий код демонстрирует общий подход:

[Embe6(source=" путьКФайлу")]

public class ИмяКласса extends ТипЭлемента {

}

При выполнении предыдущего кода внешний элемент, путь к которому определяется значением путьКФайлу, связывается с классом ИмяКласса. Класс ИмяКласса должен быть определен с использованием модификатора управления доступом public и должен расширять класс ТипЭлемента, который является одним из классов-прослоек пространства имен mx. core платформы разработки Flex, предназначенных для встраивания элементов. В последующих разделах будет рассмотрено, какие конкретные классы-прослойки должны применяться для различных типов элементов, встраиваемых на уровне класса.

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

Чтобы создать новый экземпляр элемента, встроенного на уровне класса, мы снова используем следующий стандартный код:

new ИмяКласса( );

Поддерживаемые типы элементов

При использовании тега метаданных [ Embed ] либо на уровне переменной, либо на уровне класса, поддерживаются следующие типы отображаемых элементов:

? растровые изображения в формате GIF, JPEG или PNG;

? файлы в формате SVG;

? символы из SWF-файлов предыдущих версий (то есть в формате приложения Flash Player 8 или более старых версий);

? любой файл, представляющий бинарные данные.

Кроме того, встраивание SWF-файлов целиком, независимо от их версии, поддерживается тегом [Embed] только на уровне определения переменной.

Стоит отметить, что с помощью тега метаданных [Embed] нельзя встроить отдельные символы и классы из SWF-файла в формате приложения Flash Player 9 (или более поздних версий). Вместо этого для обращения к отдельным символам и классам следует использовать один из следующих способов.



Полезные ссылки
Случайные записи
  • 24.07.2011">Управляйте мобильными с помощью компьютера
  • 02.06.2010">Самоучитель по креативному веб-дизайну. Книга 3, стр.124
  • 14.07.2011">Бюджетные ноутбуки Acer
  • 06.03.2011">Руководство по actionscript. часть 4, стр. 140
  • 03.06.2010">Самоучитель по креативному веб-дизайну. Книга 3, стр.61
  • 17.03.2011">Руководство по actionscript. часть 2, стр. 149
  • 18.05.2010">Самоучитель по креативному веб-дизайну. Книга 2, стр.69
  • 03.06.2010">Самоучитель по креативному веб-дизайну. Книга 3, стр.46
  • 15.03.2011">Руководство по actionscript. часть 3, стр. 039
  • 23.01.2011">Руководство по actionscript. часть 1, стр. 093
  • 09.03.2011">Руководство по actionscript. часть 4, стр. 067
  • 17.05.2010">Самоучитель по креативному веб-дизайну. Книга 2, стр.121
  • 22.07.2011">Интернет – кладезь для меломанов
  • 09.05.2010">Самоучитель по креативному веб-дизайну. Книга 1, стр.133
  • 17.05.2010">Самоучитель по креативному веб-дизайну. Книга 2, стр.123
Опрос

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

View Results

Loading ... Loading ...