Adobe Flex 2.0 – обзор и впечатления

Средство разработки тонких веб-клиентов

Автор: Дм. Григорьев (dimgel)
Источник: RSDN Magazine #2-2007
Опубликовано: 30.07.2007
Версия текста: 1.0
В двух словах
О технологии Flash
Достоинства
Недостатки
Новое в Flash Player 9
Новое в ActionScript 3.0 (AS3)
Новое в Flash Player 9 API
Обзор Flex
Целевое назначение, основные отличия от Flash
Формат исходных файлов
Создание своих компонент (восторг, часть первая)
Layouts
Настройка стандартных компонентов (восторг, часть вторая)
Отладка
Выводы

В двух словах

Adobe Flex – это сравнительно новая и весьма продвинутая платформа для разработки тонких Web-приложений, основанная на технологии Adobe Flash. Среда разработки представляет собой бесплатный SDK, плюс плагин Eclipse для визуального редактирования и отладки. Для выполнения кода (как и прежде, содержащегося в .swf-файлах) требуется Flash Player 9.

О технологии Flash

Flash изначально позиционировался как средство создания компактных кросс-платформенных векторных анимаций: баннеров, кнопок, меню с красивыми эффектами и т.п. Дальнейшее развитие Flash диктовалось требованиями рынка: усложнялся язык, добавлялась поддержка сложных сценариев, затем мультимедиа, интерактивность, поддержка HTTP и т.п. За отсутствием конкуренции Flash занял свою нишу целиком, и в конечном итоге стал очень мощной и широко распространённой на компьютерах пользователей платформой для разработки тонких Web-клиентов, захватив таким образом и нишу Java-апплетов.

Достоинства

Переносимость. .swf-файлы полностью независимы от платформы. Flash Plugin реализован для всех популярных платформ и браузеров. Я ни разу не сталкивался с проблемами переносимости и не слышал о существовании таковых. У Flash есть даже собственный переносимый формат видео-файлов, что делает его естественным (и, насколько мне известно, единственным) кандидатом в мультимедийные Web-платформы для таких сайтов, как, например, youtube.com.

Разработчики Flash до такой степени заботятся о сохранении кроссплатформенности, что намеренно отказываются от поддержки аппаратной акселерации графики, аргументируя это недостаточной совместимостью существующих видеокарт и недопустимостью частичной поддержки акселерации (поскольку Flash-приложение, спроектированное с учётом акселерации, в отсутствии оной будет отрисовываться недопустимо медленно, съедая всё процессорное время).

Размер и лёгкость установки. В то время как Java Runtime Environment (JRE) занимает десятки мегабайт, и часто должен скачиваться и устанавливаться пользователями вручную, Flash Plugin имеет размер 1.5MB, процесс его установки во всех браузерах максимально автоматизирован и не требует от пользователей практически никаких усилий. Разумеется, крохотный по размеру Flash Plugin не может содержать всех возможностей JRE, но для Web-приложений всё это богатство и не нужно. Библиотеки, необходимые конкретному приложению, подключаются к самому приложение, и размер результата получается вполне приемлемым.

Красота. В плане удобного и эффективного процесса создания красивых графических и анимированных интерфейсов у Flash конкурентов нет.

Распространённость. Вследствие всего вышеперечисленного, Flash Plugin установлен на компьютерах подавляющего большинства пользователей.

Недостатки

Все предыдущие версии Flash, по восьмую включительно, тащили на себе весь груз обратной совместимости, что, по моему опыту, делало разработку сложных систем на Flash малоприятным занятием. С выходом Flash Player 9 ситуация кардинально поменялась в лучшую сторону, но об этом ниже.

Количество сторонних библиотек (в частности, open-source) на порядки меньше, чем в той же Java. Те библиотеки, что я видел, в большинстве своём представляли собой визуальные компоненты и фреймворки, с массой ошибок, и в основном, являющиеся альтернативой стандартным компонентам Flash 8 Pro. Но для тонкого Web-клиента никаких особенных библиотек и не требуется.

Многие отмечают проблемы с удобством использования, а именно отсутствие поддержки многокнопочных мышей и наличие неудаляемых пунктов в контекстных меню. Насколько я успел заметить, middle click так до сих пор и не распознаётся (если быть точным, все мышиные кнопки делятся на «главную» и «любую другую»).

Новое в Flash Player 9

Основа всех возможностей Flex – это новый Flash Player. В нём реализована совершенно новая виртуальная машина AVM2, поддерживающая новую версию языка ActionScript – 3.0, а также новый реструктурированный и расширенный API.

AVM2 несовместима с виртуальной машиной AVM1, на которой базировались все предыдущие версии Flash Player. Flash Player 9 реализует обе виртуальные машины, и способен выполнять .swf-файлы любой версии. Однако имеется ограничение на взаимодействие .swf-файлов, обусловленное несовместимостью виртуальных машин. Например, вы можете загрузить Flash8-приложение внутрь Flash9-приложения, но эти два приложения будут работать в разных экземплярах VM. Как следствие, вы не сможете обращаться к данным и методам дочернего ролика из родительского приложения. Единственный возможный способ коммуникации заключается в использовании класса LocalConnection, который выполняет маршалинг вызовов методов.

Кроме того, AVM2 оптимизирована по скорости. Заявлено, что скорость работы AVM2 в десять раз выше скорости AVM1. Что именно измерялось – вычисления или рендеринг графики, лично мне не известно.

Новое в ActionScript 3.0 (AS3)

Улучшенная обработка ошибок. Предыдущие версии Flash Player молча обрабатывали такие случаи, как обращение к несуществующим свойствам или к свойствам null-объекта, возвращая undefined. Зачастую это было удобно с точки зрения компактности кода, но крайне проблематично с точки зрения отладки. Flash Player 9 генерирует исключение при любой ошибке, при этом неперехваченное исключение показывается пользователю в отдельном окне.

Проверка типов во время исполнения. В ActionScript 2 (AS2) указания типов переменных служили исключительно подсказками программисту и компилятору. Если в процессе компиляции обнаруживалось несоответствие типов, компилятор генерировал ошибку, но в результирующий .swf-файл никакой информации о типах не помещалось. Теперь такая информация помещается в результирующий файл, и AVM2 использует ее для проверки типов во время выполнения, генерируя исключение в случае несоответствия типов. Если же информация о типах в исходном тексте не указана (как например, при работе с Object или XML), используется динамическая типизация, аналогичная предыдущим версиям Flash.

Добавились новые элементарные типы данных, такие как int, uint. Раньше был только один универсальный тип Number – он также остался в AS3. Кроме того, изменились значения по умолчанию для не инициализированных переменных. В частности, для объектов (в т.ч. String) используется null, для int и uint – 0; значение undefined используется только с переменными необъявленного типа.

Улучшенная объектная модель. Поддержка модификатора protected, и некоторых других спецификаторов.

"Запечатанные" (sealed) классы.

В ActionScript 3.0 появилась концепция sealed-классов. Такой класс имеет только фиксированный набор свойств и методов, который не подлежит расширению во время исполнения. Это позволяет усилить контроль со стороны компилятора, тем самым оберегая программиста от случайных ошибок. По умолчанию классы являются запечатанными. Для поддержки динамических свойств и методов необходимо использовать ключевое слово dynamic в объявлении класса.

Замыкания методов. Указатель на метод (тип Function) теперь содержит в себе указатель на его объект. Раньше приходилось использовать вспомогательный класс Delegate или же извращаться другими способами.

Регулярные выражения, в соответствии со стандартом ECMA-262 (т.е. полностью аналогично JavaScript).

Удобная работа с XML в соответствии со стандартом ECMAScript for XML (E4X). Несколько примеров скажут сами за себя:

        var xmlResponse: XML = <response status="ok">
<some-int>1234</some-int>
<clients>
<r id="1"><name>Иванов</name><balance>10</balance></r>
<r id="2"><name>Петров</name><balance>1000</balance></r>
</clients>
</request>;
if (xmlResponse.@status == "ok") {
    var someint: int = xmlResponse.child('some-int');  // (1) okvar richClients: XMLList = xmlResponse.clients.r.(balance > 0); // (2) okvar richClientId: int = richClients[0].@id;  // (3) ok
    richClientId = richClients.@id;  // (4) ошибка
    richClientId = xmlResponse.clients.@id;  // (5) ошибка
    xmlResponse.clients.r.(@id==1).balance = 2000;  // (6) ok
}

При работе с XML используется автоматическое приведение типов. В приведенном примере, в строках (1) и (3) целочисленным переменным присваиваются значения XML-элементов и атрибутов, без явного преобразования типов. Также XMLList, содержащий один элемент, может быть приведён к XML (часть выражения слева от balance в строке (6)). Однако в строках (4) и (5) возникает исключение при попытке привести двухэлементный XMLList к XML.

Новое в Flash Player 9 API

Во-первых, API реструктурирован. Все классы, реализуемые Flash Player 9, теперь находятся в пакете flash. Например, API работы с сетью находится в пакете flash.net, экранно-визуальное API – в пакете flash.display и т.д. Также приведена в порядок иерархия классов.

Улучшена работа с деревом визуальных объектов. Прошлые извращения createEmptyMovieClip(), createTextField(), attachMovie(), removeMovieClip(), removeTextField() канули в лету. Сейчас всё выглядит очень удобно и похоже на DOM, например:

        import
        /*...*/;
...
// mx.containers.Grid - layout-контейнер, 
// как таблица с невидимой сеткой в HTML.var grid = new Grid();  
var row = new GridRow();
var cell1 = new GridItem1();
var lbl = new Label();
lbl.text = "Hello world";
cell1.addChild(lbl);
row.addChild(cell1);
var cell2 = new GridItem1();
row.addChild(cell2);
grid.addChild(row);
Application.application.addChild(grid);
...
// Перемещаем lbl к другому родителю в визуальной иерархии.
cell2.addChild(lbl);  
...
// Удаляем lbl из визуальной иерархии.
Cell2.removeChild(lbl); 
// Удаляем lbl из памяти.
lbl = null;  

В предыдущих версиях Flash Player API обработка событий производилась путем подмены метода-обработчика события. Такая подмена могла быть произведена или путем создания наследника класса, содержащего новый вариант метода, или динамической заменой метода у конкретного объекта. В новой версии для обработки событий используется DOM3 Event Model, т.е. методы addEventListener() и removeEventListener(). Это позволяет добавлять более одного обработчика событий для одного события.

Переделана работа с сетью. Новый класс Socket обеспечивает низкоуровневую работу с сокетами, с удобной сериализацией двоичных данных (например, методы readInt(), readDouble(), readUTF(), writeBytes(), writeUTFBytes() и т.д.). При желании вы можете, опираясь на сокеты, написать, например, собственный почтовый клиент. (Готовых SMTP и POP3-клиентов я в Flex2 не нашёл; видел только HTTP и SOAP.)

Классы LoaderInfo (используемый загрузчиком .swf-файлов и файлов изображений) и URLLoader (загрузчик текстовых и двоичных данных) теперь используют DOM3 Event Model и одинаковый набор событий для оповещения о состоянии процесса загрузки.

ПРИМЕЧАНИЕ

К сожалению, остались неисправленными недостатки класса FileReference, ответственного за загрузку файла на сервер. Коды ошибок, кроме 404, обрабатываются некорректно. И, что хуже всего, отсутствует возможность получить содержимое ответа, то есть возможность анализа результата операции загрузки сводится к проверке булева условия status==200. Для получения любой другой информации приходится использовать сессии и дополнительный HTTP-запрос.

Улучшена работа с текстом. Все соответствующие API вынесены в пакет flash.text. Класс TextLineMetrics позволяет рассчитывать метрики текста. В классе TextField появилось несколько новых методов: getCharBoundaries() и getCharIndexAtPoint() для перевода индекса символов в пиксельные координаты и обратно; getFirstCharInParagraph(), getParagraphLength(), getLineLength(), getLineText(), getLineIndexOfChar() для работы со структурой текста. Новый класс Font предназначен для работы со шрифтами, внедрёнными в .swf-файл.

Обзор Flex

Среда разработки Flex основана на Eclipse. Eclipse SDK (http://www.eclipse.org/) – это написанная на Java кроссплатформенная, открытая, универсальная среда разработчика. Под универсальностью понимается наличие плагинов поддержки самых разных языков – Java, C++, PHP и т. д. Встроенные средства Eclipse, такие как оконный интерфейс, редактор, поддерживающий подсветку синтакса, отладчик и прочие, доступны программистам на всех поддерживаемых языках.

Пробную версию инсталлятора Flex можно скачать с сайта Adobe (http://www.adobe.com/). Инсталлятор содержит в себе бесплатный Flex SDK (набор утилит командной строки для компиляции, генерации документации и т. д.), Flex plugin для Eclipse, а также собственно Eclipse SDK для тех, у кого Eclipse не установлен. При запуске инсталлятор предлагает выбор – либо ставить Flex plugin в каталог с уже установленной Eclipse (путь к каталогу запрашивается), либо установить Eclipse и Flex plugin в новый каталог.

Целевое назначение, основные отличия от Flash

Несмотря на то, что в качестве платформы Flex использует Flash Player, с точки зрения разработчика Flash CS3 и Flex 2 имеют мало общего. Общие у них только ActionScript 3.0 и Flash Player 9 API.

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

Flex заточен под разработку rich internet applications, под визуализацию и обработку данных. Я бы рискнул сравнить его с Delphi: тот же стандартный набор компонентов, включая data-aware, для быстрого построения пользовательских интерфейсов.

ПРИМЕЧАНИЕ

Недавно вышедший Flash CS3 я ещё не видел, поэтому всюду, где я ссылаюсь на Flash, я имею в виду Flash 8 Pro. Возможно, некоторые мои сравнения с выходом Flash CS3 потеряли смысл. Заранее прошу прощения за возможные несоответствия.

Flex не предоставляет таких средств, как рисование векторных изображений и анимации. Предполагается, что при необходимости использования .swf-анимаций в качестве элементов оформления, разработчик импортирует готовые анимации из Flash. Однако в Flex предусмотрен набор стандартных эффектов, таких как движение, размывание, изменение цвета или альфа-канала и т.п. Также имеются средства группировки эффектов, с параллельным или последовательным выполнением, с возможностью вложения групп. Эффекты удобно использовать, например, для анимации выпадающих меню.

ПРИМЕЧАНИЕ

Разумеется, вы можете рисовать векторные изображения программно (а также программно отображать внедрённые в .swf-файл или динамически загружаемые растровые изображения). Но этот подход эффективен в очень ограниченном количестве случаев.

Как следствие, на уровне исходных текстов Flex отсутствует понятие «timeline». Вместо этого в визуальном редакторе имеется возможность задавать состояния объекта. Для каждого состояния указывается, какие объекты нужно добавить или удалить, а также какие свойства объектов изменить – по сравнению с базовым состоянием.

ПРИМЕЧАНИЕ

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

Формат исходных файлов

Файлы MXML

В отличие от Flash, хранящего исходный код форм и анимации в закрытом двоичном формате, формат исходных файлов Flex базируется на XML; файлы имеют расширение mxml. Формат MXML весьма компактен и очень удобен для редактирования вручную; сделанные вручную изменения подхватываются визуальным редактором. Вот пример исходного файла простенького Flex-приложения, содержащего кнопку «Say Hello», при нажатии на которую появляется окошко с сообщением «Hello world»:

Файл FlexProject.mxml

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
  <mx:Script>
    <![CDATA[
      import mx.controls.Alert;

      privatefunction sayHello() : void
      {
        Alert.show("Hello world!", "Box Title", Alert.OK);
      }
    ]]>
  </mx:Script>
  <mx:Button horizontalCenter="0" verticalCenter="0" 
      label="Say Hello" click="sayHello()"/>
</mx:Application>

В этом примере атрибуты кнопки horizontalCenter и verticalCenter указывают смещение в пикселях относительно центра родительского объекта (в данном случае кнопка строго центрирована в рабочей области приложения). Третий параметр метода Alert.show() является необязательным; я добавил его в качестве намёка, что Alert – это полноценный message box с возможностью настройки набора отображаемых кнопок и обработки ответа пользователя.

На самом деле каждый mxml-файл представляет собой класс. Корневой элемент задаёт имя базового класса, в вышеприведенном примере это mx.core.Application. Функции, объявленные внутри элемента <mx:Script>, являются методами. Flex обрабатывает mxml-классы и ActionScript-классы практически одинаковым образом, то есть позволяет организовывать их в пакеты, наследовать и создавать их экземпляры.

Файлы ActionScript

Аналогично Flash, вы можете создавать свои классы на языке ActionScript, организуя их в пакеты. Структура каталогов в дереве исходных файлов проекта должна отражать структуру пакетов. Например, я унаследовал класс dimgel.HtmlEditor от mx.controls.RichTextEditor, ограничив количество доступных пользователю кнопок:

Файл dimgel/HtmlEditor.as

          package dimgel {
    import mx.controls.RichTextEditor;
    import mx.events.FlexEvent;

    publicfinalclass HtmlEditor extends RichTextEditor {
        publicfunction HtmlEditor() {
            addEventListener(FlexEvent.CREATION_COMPLETE, 
                    onCreationComplete);
        }

        privatefunction onCreationComplete(e:FlexEvent): void {
            toolbar.removeChild(fontFamilyCombo);
            toolbar.removeChild(fontSizeCombo);
            ...
        }
    }
}

Импорт

Для импорта классов в ActionScript-код используется оператор import, как показано в примере выше. Для импорта компонентов в mxml-файл используются пространства имён XML. Например, после того, как я перетащил мышью компонент dimgel.HtmlEditor из панели компонентов в визуальный редактор приложения, mxml-файл стал выглядеть так:

Файл FlexProject.mxml

<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"xmlns:ns1="dimgel.*">
    ...
    <ns1:HtmlEditor .../>
</mx:Application>

Создание своих компонент (восторг, часть первая)

По сравнению с Flash 8, процедура создания компонентов стала удобнее и проще на порядки. Никаких компиляций в .swc и копирований в специальные каталоги. В Flex компонент – это просто класс (ActionScript или mxml-файл) в дереве проекта, являющийся подклассом одного из стандартных визуальных компонентов. Например, чтобы создать подкласс dimgel.RedLabel класса mx.controls.Label, отображающий текст красным цветом, можно использовать два способа:

Способ 1 (ActionScript). Файл dimgel/RedLabel.as
        package dimgel 
{
  import mx.controls.Label;

  publicfinalclass RedLabel extends Label 
{
    publicfunction RedLabel() 
{
      setStyle('color', '#FF0000');
    }
  }
}
Способ 2 (MXML). Файл dimgel/RedLabel.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:Label xmlns:mx="http://www.adobe.com/2006/mxml" color="#FF0000"/>
ПРЕДУПРЕЖДЕНИЕ

Обратите внимание, что имя компонента, описанного в XML, определяется именем файла, в который он помещается – прим.ред.

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

В MXML:

<ns1:RedLabel text="Hello red world!"/>

В ActionScript:

        var redLabel = new RedLabel();
redLabel.text = "Hello red world!";
this.appendChild(redLabel);

Единственное отличие между описанными способами создания класса компонента заключается в том, что визуальный дизайнер не подхватывает логику, прописанную в ActionScript-коде. Например, компонент RedLabel, созданный с помощью ActionScript, в визуальном дизайнере будет отображаться чёрным. Но в откомпилированной программе различий не будет.

ПРИМЕЧАНИЕ

В случае визуального дизайна компонента mxml-файл не содержит информации о принадлежности к пакету. Таким образом, чтобы переместить mxml-компонент в другой пакет, достаточно переместить файл в соответствующий каталог. Для перемещения AS-компонента нужно ещё исправить имя пакета в директиве package.

Layouts

Возможности абсолютного позиционирования визуальных компонентов внутри визуальных контейнеров намеренно ограничены. Вместо абсолютного позиционирования рекомендуется использовать специальные компоненты – layout-контейнеры. Например, чтобы расположить кнопки на панели инструментов горизонтально друг за дружкой, можно использовать компонент HBox:

<mx:HBox horizontalGap="5">
    <mx:Button .../>
    <mx:Button .../>
    ...
</mx:HBox>

Аналогично, имеются контейнеры для выстраивания дочерних компонентов вертикально (VBox), в сетку (Grid, Tile) и т. д., а также масса вспомогательных компонентов (Spacer, HRule, VRule и т.д.). Можно указывать размер компонентов, находящихся внутри layout-контейнеров, но нельзя указать их координаты, поскольку объекты позиционируются контейнером автоматически. Единственный layout-контейнер, допускающий абсолютное позиционирование компонентов, - это Canvas (который также является рабочей областью компонентов Panel, TitleWindow, ViewStack и т.п.).

Пример исходного кода диалога, внизу-посередине которого находятся две кнопки (“OK” и “Cancel”), а всю остальную область занимает текстовое поле:

Файл dimgel/TextInputBox.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:TitleWindow xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" 
        width="300" height="200" title="Введите текст">
    <mx:VBox left="10" right="10" top="10" bottom="10" verticalGap="10">
        <mx:TextInput id="mytxt" width="100%" height="100%" text="Текст."/>
        <mx:HBox width="100%" horizontalAlign="center">
            <mx:Button label="OK"/>
            <mx:Button label="Cancel"/>
        </mx:HBox>
    </mx:VBox>
</mx:TitleWindow>

Результат:


Настройка стандартных компонентов (восторг, часть вторая)

Кто программировал на Delphi или Flash 8, тот помнит, в какую головную боль выливались попытки раскрасить строки DataGrid в разные цвета, или назначить им разные шрифты в зависимости от находящихся в них данных, не говоря уже о чём-либо более сложном. В Flex эта проблема решена через использование Item Renderers и Item Editors. Списки, комбобоксы, столбцы таблиц и т.д. – очень многие компоненты позволяют замещать свои стандартные рендереры. При этом на пользовательский рендерер не налагается практически никаких ограничений – это может быть любой компонент произвольного (в том числе динамического) размера, содержащий в себе другие компоненты, подгружаемые или внедрённые картинки, сложный layout и т.д.

Пример 1 (из документации).
<mx:DataGrid dataProvider="{xmlResponse.clients.r}" variableRowHeight="true" editable="true">
  <mx:columns>
    <mx:DataGridColumn dataField="label1" headerText="Order #"/>
    <mx:DataGridColumn dataField="quant" editorDataField="value">
      <mx:itemEditor>
        <mx:Component>
          <mx:NumericStepper stepSize="1" maximum="50"/>
        </mx:Component>
      </mx:itemEditor>
    </mx:DataGridColumn>
  </mx:columns>
</mx:DataGrid>

В этом примере, в числе прочего, демонстрируется объявление анонимного компонента (itemEditor) по месту. Для разграничения областей видимости (scope) используется специальный элемент <mx:Component>, внутри которого содержится объявление анонимного класса-рендерера (в нашем примере – подкласса NumericStepper). Экземпляр этого класса назначается свойству itemEditor объекта DataGridColumn (тип свойства – IFactory, генератор классов). Альтернативой является создание компонента-подкласса класса NumericStepper и указание его имени в свойстве itemEditor:

<mx:DataGrid dataProvider="{xmlResponse.clients.r}" variableRowHeight="true" editable="true">
  <mx:columns>
    <mx:DataGridColumn dataField="label1" headerText="Order #"/>
    <mx:DataGridColumn dataField="quant" editorDataField="value" 
                                                  itemEditor="NumericStepperSubclass"/>
  </mx:columns>
</mx:DataGrid>

Подобный стиль объявлений "по месту" интенсивно используется для инициализации свойств компонентов, в том числе свойств-коллекций. В вышеприведённом примере свойство DataGrid.columns является коллекцией объектов DataGridColumn. Аналогичный стиль может использоваться, например, для инициализации списка элементов ComboBox и т.д.

Файл dimgel/ObjectRemarkRenderer.mxml

<?xml version="1.0" encoding="utf-8"?>
<mx:Text xmlns:mx="http://www.adobe.com/2006/mxml" preinitialize="initMe()" 
         selectable="false">
  <mx:Script>
    <![CDATA[
      privatefunction initMe(): void {
        addEventListener('dataChange', onDataChange);
      }

      privatefunction onDataChange(event:Event): void {
        var s:String = data.remark;
        // Берем содержимое элемента <remark>.
        s = s.replace(/^<remark>(.*)<\/remark>/, '$1');
        htmlText = XML(s);
      }
    ]]>
  </mx:Script>
</mx:Text>

Экземпляры рендереров кэшируются и используются повторно. Поэтому рендерер должен обрабатывать событие dataChange, чтобы обновлять и перерисовывать себя. Свойство data является частью интерфейса IDataRenderer, который реализует компонент mx.controls.Text, используемый здесь в качестве базового класса. Пример использования рендерера, описанного в файле ObjectRemarkRenderer.mxml, приведён ниже:

Файл dimgel/Objects.mxml
<?xml version="1.0" encoding="utf-8"?>
<mx:Canvas xmlns:mx="http://www.adobe.com/2006/mxml" width="1000" height="500" 
           creationComplete="onCreationComplete()" show="onShow()">
  ...
  <mx:DataGrid width="100%" height="100%" variableRowHeight="true" 
      change="onCurrentObjectChange()">
    <mx:columns>
      <mx:DataGridColumn headerText="Код" dataField="id"/>
      ...
      <mx:DataGridColumn headerText="Примечания" dataField="remark" 
          itemRenderer="dimgel.ObjectRemarkRenderer"/>
      <mx:DataGridColumn headerText="Цена" dataField="price"/>
    </mx:columns>
  </mx:DataGrid>
</mx:Canvas>

Свойство DataGrid.variableRowHeight уставлено в true, в противном случае высота всех строк таблицы устанавливается одинаковой, равной максимальной высоте содержащихся в строках данных (в нашем случае – максимальной высоте HTML-текста, отображаемого рендерером).

Отладка

Появилась возможность отладки из браузера. Теперь можно отлаживать .swf-файлы, загруженные по HTTP, то есть вы нажимаете кнопку “Debug” в Eclipse, отладочная версия компилируется и открывается в браузере через HTTP, при этом отладчик Eclipse подключается к Flash-плагину браузера.

Отладчик Flash 8 мог загружать .swf-файл только из локальной файловой системы, что было крайне неудобно, поскольку отлаживаемый .swf не мог обращаться к http:// из-за ограничений песочницы.

Выводы

Появление Flash Player 9 ознаменовало давно ожидаемый качественный скачок Flash как платформы для разработки сложных Web-приложений. Освободившись от груза обратной совместимости, новый Flash вобрал в себя богатый опыт прошлого и стал действительно удобным для разработчиков.

Flex, сфокусировавшись на разработке Web-приложений, предоставляет сбалансированный инструментарий, скрывает несущественные с точки зрения разработчика детали функционирования Flash Player, заменяя их высокоуровневыми абстракциями. Библиотека классов и выразительные возможности Flex чрезвычайно продуманы, способны обеспечить высокую эффективность разработки. А богатство возможностей Flash, удобство использования и переносимость сгенерированного кода вполне могут позволить ему конкурировать с AJAX.

Посмотреть, как выглядит работающее Flex-приложение, сделанное на стандартных компонентах и без изысков, можно здесь: http://dimgel.ru/poiskgel.ru/admin/. Это моё первое Flex-приложение, интерфейс администрирования для сайта http://dimgel.ru/poiskgel.ru/. Это тестовый пример, так что вы можете добавлять, редактировать и удалять всё, что угодно (оставаясь в рамках приличий). Примеры запросов к серверу, которые делает интерфейс администрирования: http://dimgel.ru/poiskgel.ru/admin/GetLists.php, http://dimgel.ru/poiskgel.ru/admin/GetCategories.php. Баг-репорты привествуются, пожелания по улучшению – только за дополнительную плату. ;)


Эта статья опубликована в журнале RSDN Magazine #2-2007. Информацию о журнале можно найти здесь