Рубрики: Flash, flash player, Flash+Flex
Data Binding во Flex. Часть 1. Немного общих слов и истории
Это первая часть моего рассказа про Data Binding во Flex, который живьем можно было послушать на 12-ого апреля 2008 года на питерской встрече Russian Adobe Flash Platform User Group.
Презентацию можно скачать здесь, либо посмотреть в отчете Константинера о встрече RAFPUG в Питере в День Космонавтики.
Презентация рассчитана на мой сопутствующий рассказ, поэтому некоторые слайды можно неправильно воспринять без объяснений. Отчасти поэтому я и пишу небольшой цикл постов по этой теме. Хотя главная причина в том, что тема эта очень интересная, и хочется говорить об этом снова и снова. ![]()
Data Binding (связывание данных) можно назвать одной из основ разработки на Flex. Поэтому каждый уважающий себя разработчик прямо таки обязан в совершенстве владеть этим интересным и полезны механизмом.
Если вы разрабатываете на Flex, то, скорее всего, регулярно используете data binding. Особенно органично его использование в mxml. Вообще говоря, надо сильно извратиться, чтобы, используя mxml, ни разу не использовать data binding или связывание данных.
Data binding во Flash
Интересно, что на Flash платформе data binding появился еще во Flash, и некоторые разработчики активно его использовали.
Flash 8 для этого предоставлял Bindings tab и классы пакета mx.data.binding.
Кстати, не могу сказать, что связывание данных во Flash, было удобным. Хотя, не могу сказать, что хоть что-то там было удобно. ![]()
Еще более интересен тот факт, что Flash CS3 уже не предоставляет возможностей связывания данных своим разработчикам. Видимо, это очередной намек Adobe на то, что программистам надо смотреть в сторону Flex.
В документации для Flash CS3 про Data binding classes недвусмысленно говорится о том, что можно использовать старые механизмы связывания, но тогда и компилить можно будет только под ActionScript 2.0.
Что же такое связывание данных или data binding?
Суть связывания в автоматической синхронизации. Слово “автоматическая” особенно приятно звучит, так как это освобождает нас от какой-то рутинной работы. А кто хочет заниматься рутинной работой? ![]()
Наиболее распространенный случай - это синхронизация model и view.
При нормальном адекватном развитии событий в приложении существуют такие слои, как view, model, controller. View отображает данные модели. В большинстве случаев при изменении данных в модели, необходимо обновлять view. Это можно осуществить вручную путем подписывания на события изменения модели и вызовом методов обновления view. Связывание данных позволяет делать это автоматически.
Вам выбирать, что синхронизировать. Это может быть синхронизация данных, различных элементов GUI и тд и тп.
В качестве примера синхронизации элементов GUI можно привести такой код:
Code:
<mx:List id="list1" dataProvider="{listExample}"></mx:List> | |
<mx:List id="list2" dataProvider="{listExample}" | |
selectedIndex="{list1.selectedIndex}" | |
verticalScrollPosition="{list1.verticalScrollPosition}"> | |
</mx:List> |
Всего несколько строк кода позволяют определить сразу три синхронизации:
- dataProvider обоих списков синхронизируются с коллекцией listExample. Это значит, что при изменении listExample, оба списка сами обновят свой внешний вид.
- selectedIndex синхронизируется с соответствующим свойством первого списка. Таким образом, когда пользователь выделяет элементы первого списка, соотвествующие элементы автоматически выделяются во втором списке.
- аналогично синхронизируются значения verticalScrollPosition списков. Если пользователь скролит первый список, то автоматически скролится и второй список.
Russian Flash Platform User Group
Свершилось! Поздравляю всех поклонников и почитателей Flash Platform! ![]()
Читаем про Russian Flash Platform User Group в посте у Constantiner.
Конечно же, все бежим срочно присоединятся к группе.
Смотрим календарь группы и видим, что первая встреча скоро состоится в Москве.
Ну что же. Будем ждать встречи и в Питере. ![]()
Особенности дебага на Mac OS
Обнаружилась проблема. Debug версия 9-ого flash player никак не хотела писать лог на Mac OS.
Починить это удалось только путем ручного создания файла
MacHD:Library:Application Support:macromedia:mm.cfg вот с таким содержимым:
ErrorReportingEnable=0
TraceOutputFileEnable=1
MaxWarnings=500
После этого flash player создал файл flashlog.txt в папке
Users/user_name/Library/Preferences/Macromedia/Flash Player/Logs/
и начал таки его использовать по назначению.
Впечатления от Client Side'2007
Constantiner в своем посте ClientSide-2007: впечатления уже про многое написал. Теперь мои впечатления. ![]()
Конечно, самой интересной для меня оказалась секция “Мультимедиа". Но и в других секциях было, на что посмотреть.
Сравнение современных технологий для создания насыщенных интернетприложений (RIA)
Те, кто не знали о происхождении понятия RIA, узнали, что своим появлением оно обязано старой доброй Macromedia. И что все люди используют расшифровку Rich Internet Applications, а Microsoft - Rich Interactive Applications.
Проводилось исчерпывающее сравнение технологий: Flex, Flash, AIR, Silverlight, WPF и JavaFX. Было рассмотрено большое количество различных характеристик и очень жаль, что не про все Костя успел рассказать. На основании сравнения не были сделаны какие-либо выводы, так что все сделали свои выводы самостоятельно и получили обзорное представление о наиболее популярных RIA-технологиях.
Adobe Integrated Runtime (Adobe AIR): платформа для создания десктопных RIA
Данная платформа позволяет создавать десктопные RIA, то есть расширяет область использования и возможности привычных RIA работающих в браузере.
Adobe AIR представляет собой технологию, интегрирующую в себя Flash/Flex, HTML/DHTML/JavaScript/AJAX и PDF и позволяет разрабатывать или просто портировать веб-приложения на десктоп.
Была рассмотрена тема которая интересовала многих - зачем вообще нужны RIA на десктопе? Я для себя лично отметила две основных и взаимосвязанных причины - проблема работы в оффлайне и хранение данных на клиенте. Все-таки всякое бывает в жизни, и могут быть варианты, когда оффлайн работа очень нужна. Я бы например, с удовольствием отказалась от параллельного использования почтовых программ и веб-интерфейса в пользу одного десктопного RIA.
AIR позволяет использовать встроенную базу данных SQLite или хранить необходимые данные просто в файлах на локальном компьютере. Кстати, SQLite использует и Google Gears, про который рассказывалось в докладе Оффлайн веб-приложения: от Google Gears до HTML5 в секции “AJAX, JavaScript, JSON".
В общем, рассказ про новую технологию Adobe Integrated Runtime произвел очень большое впечатление. После доклада заинтересованные буквально засыпали вопросами Костю. А так как времени на вопросы не оставалось, и вопросы задавались уже в коридоре, то многие пропустили доклад Работа с данными в формате XML в среде Adobe Flash. Создание standalone приложений с использованием Adobe Flash и Northcode SWF, и я была среди многих, так что буду ждать появления материалов для ознакомления.
Мастеркласс «Геометрия во Flash: кривые Безье второго порядка»
Иван прямо-таки не пожалел зрителей и провел краткий экскурс в математику кривых Безье, с раскрытием их геометрического смысла и особенностей построения.
Рассказал о том, зачем простому смертному нужны эти кривые и представил свой проект www.bezier.ru. Если вы занимаетесь разработкой игр, то вам скорее всего будет особенно интересен этот проект.
Технология Google Web Toolkit
Google Web Toolkit (GWT) - технология имеющая своими целями создание desktop-like веб-приложений, позволяющая разрабатывать их на языка Java (с последующей компиляцией в JavaScript).
Технология имеет ряд преимуществ, таких как использование CSS, эффективная загрузка картинок, поддержка истории браузера, статическая и динамическая локализация, простая интеграция с Java бекендом, desktop-like интерфейс и т. д. Существуют и недостатки, среди которых сложный UI, который может занимать много памяти и времени CPU на клиенте.
Анимационные эффекты средствами браузера
Речь шла об основах анимации средствами JavaScript, а также о существующих фреймворках, позволяющих упростить процесс создания анимации (script.aculo.us, Dojo, jQuery и др).
Был дан ряд советов, позволяющих улучшить производительность - минимальное использование прозрачности, использование одного общего таймера и др.
Оффлайн веб-приложения: от Google Gears до HTML5
30 мая 2007 года Google анонсировала свой проект с открытым исходным кодом — Google Gears для решения проблемы работы web-приложений в оффлайне.
Тогда же было принято решение ввести стандартизацию веб-приложений, работающих без подключения к сети в рамках спецификации Web Applications 1.0, также известной как HTML 5.
Какие же проблемы решает Google Gears? Это кеширование приложения, хранение локальных данных, отложенная загрузка файлов на сервер и др.
Но по сути, Google Gears является временным решением до прихода эры HTML 5.
Автоматизация тестирования сложных Flash интерфейсов
Этот доклад был в секции “Качество, тестирование". Автор озабочен решением проблемы тестирования сложных Flash интерфейсов и предлагает свой вариант - это использование Selenium и связки ExternalInterface + JavaScript.
У данного подхода есть плюсы и минусы, но одно радует - эта проблема волнует умы, и решения существуют.
Подводя итог поездке на Client Side’2007, могу сказать, что было очень интересно. На мой взгляд, конференция удалась. Было много возможностей пообщаться с коллегами и обменяться опытом.
Будем ждать новых интересных конференций и успешного создания “Flash Platform User Group или что-то в этом роде” ©Constantiner.
Пример для Flex Component Kit for Flash CS3
Интерфейсы в actionscript 2.0. Часть 3. Много – лучше, чем один
В конце прошлой части я затронула вопрос о том, что есть смысл избегать использования интерфейсов, включающих в себя много различных и не связанных друг с другом методов. Использование таких раздутых интерфейсов может иметь далеко идущие последствия. Помимо появления объектов с пустыми методами (см. часть 2), некоторые идеологические несовершенства со временем могут привести к практическим сложностям.
Приведем пример ‘неправильного’ интерфейса, чтобы было понятно, о чем речь. Пусть у нас есть графический редактор. Будем использовать интерфейс IEditableObject для однообразного общения системы с элементами (линия, текст, картинка, видео и т. п).
- /**
- * Редактируемый объект.
- * @author J.Nikolaeva
- * @version 22.01.2007
- */
- interface IEditableObject {
- /**
- * Ширина объекта.
- * @return ничего
- */
- public function getWidth():Void;
- /**
- * Высота объекта.
- * @return ничего
- */
- public function getHeight():Void;
- /**
- * Установка размеров.
- * @param w ширина
- * @param h высота
- * @return ничего
- */
- public function setSize(w:Number, h:Number):Void;
- /**
- * Установка цвета.
- * @param color цвет
- * @return ничего
- */
- public function setColor(color:Number):Void;
- /**
- * Цвет объекта.
- * @param
- * @return
- */
- public function getColor():Void;
- /**
- * Обновление вида объекта, после изменения соответствующих данных.
- * @return ничего
- */
- public function update():Void;
- /**
- * Создает полную копию объекта.
- * @return копия объекта
- */
- public function clone():IEditableObject;
- }
Все, кто имеет дело с объектами типа IEditableObject, будут в курсе ‘личной жизни’ этих объектов - у них есть и цвет, и размер, и более того, они могут обновляться после каких-то изменений и даже производить своих клонов. Вряд ли все описанные методы могут быть использованы каким-то модулем одновременно. Использование интерфейса типа IEditableObject, говорит о растущей вероятности того, что принцип низкой связанности и высокого зацепления в приложении не сможет выполняться.
Вместо того, чтобы интерфейс сообщал о конкретных, необходимых определенному модулю, возможностях, он будет пытаться объять необъятное - сообщить всем модулям обо всех своих возможностях. А ведь в идеале, каждый модуль должен ‘видеть’ только ‘свои’ методы, то есть методы, которые он будет реально использовать.
Особенно такие откровенные интерфейсы неудобны при командной разработке, когда не все участники процесса должны знать о таких опасных возможностях как создание клонов. А со временем, в интерфейс будут добавляться все новые и новые методы, в ворохе которых смогут разобраться только самые усидчивые и терпеливые разработчики. А главное, будет уже совсем не понятно, что именно могут экземпляры этого интерфейса.
Как избежать выше описанных проблем и не разувериться в возможностях применения интерфейсов?
Можно ‘разделить’ интерфейс IEditableObject на несколько более удобных интерфейсов: IResizable, IСolorChangeable, IDataDependent, ICloneable. Теперь видно, какое поведение определяется каждым интерфейсом.
Вот пример кода, иллюстрирующий использование новых интерфейсов.
- /**
- * Контроллер всего графического редактора.
- * @author J.Nikolaeva
- * @version 22.01.2007
- */
- class EditorController {
- private var archive:CopiesArchive;
- /**
- * Конструктор.
- */
- public function EditorController() {
- archive = new CopiesArchive();
- }
- public function addLine():Void {
- var line:Line = ElementsFactory.createLine();
- archive.addElement(line);
- }
- }
- /**
- * Линия.
- * @author J.Nikolaeva
- * @version 23.01.2007
- */
- class Line implements IResizable, IColorChangeable, IDataDependent, ICloneable {...}
- /**
- * Архив копий объектов.
- * @author J.Nikolaeva
- * @version 23.01.2007
- */
- class CopiesArchive {
- /**
- * Конструктор.
- */
- public function CopiesArchive() {
- }
- public function addElement(element:ICloneable):Void {
- }
- }
Рассмотрим метод addLine в классе EditorController. Видно, что несмотря на то, что мы получаем от ElementsFactory соврешенно конкретный элемент типа Line, класс CopiesArchive ‘знает’ объект только по интерфейсу ICloneable, то есть знает только то, что этот элемент имеет метод clone. Таким образом мы сможем помещать в архив любые элементы реализующие интерфейс ICloneable, даже если это вообще не элемент редактора, а какая-то другая сущность. А это было бы невозможно при использовании интерфейса IEditableObject.
Интерфейсы в actionscript 2.0. Часть 2. Одинаковое поведение - разная реализация
Наверное самый распространенный случай использования интерфейсов следующий.
В приложении существует некоторое количество объектов, которые обладают одинаковым поведением, но имеют разную реализацию и не подпадают под случай возможности или рациональности наследования их от одного предка. А так случается часто, ведь у наследования, помимо такого плюса как повторное использование кода, существует и минус - бОльшая связанность, чем при использовании интерфейсов. Нерациональное использование наследования может привести к огромной и подчас неуправляемой иерархии классов, которые сложно поддерживать и использовать.
Рассмотрим пример.
Пусть существует графический редактор с различными панелями и модулями. Необходимо сохранять расположение и настройки этих панелей для следующего сеанса работы с пользователем. Система каждый раз при закрытии, опрашивает все панели на предмет сохраняемых данных, а при следующей загрузке раздает данные обратно. В этом случае можно реализовать интерфейс IRestoreable с методами getRestoreData и setRestoreData, которые служат для получения и установки данных в панель или модуль.
Пример интерфейса.
- /**
- * Интерфейс для элементов с восстанавливаемым состоянием.
- * @author J.Nikolaeva
- * @version 20.12.2006
- */
- interface IRestoreable {
- /**
- * Возвращаем данные о состоянии.
- * @return данные о состоянии
- */
- public function getRestoreData():PanelStateData;
- /**
- * Установка данных о состоянии.
- * @param data - данные о состоянии
- * @return ничего
- */
- public function setRestoreData(data:PanelStateData):Void;
- }
Теперь если реализовать данный интерфейс для панелей и модулей редактора, то можно будет общаться с ними единообразно. Например, пусть классы SizePanel и ColorMixerPanel реализуют данный интерфейс. Из следующего примера понятно, в каком русле можно организовать общение главного приложения с ними.
- /**
- * Приложение графический редактор.
- * @author J.Nikolaeva
- * @version 20.12.2006
- */
- class Application {
- private var sizePanel:IRestoreable;
- private var colorMixer:IRestoreable;
- /**
- * Конструктор.
- */
- public function Application() {
- sizePanel = new SizePanel();
- colorMixer = new ColorMixerPanel();
- sizePanel.setRestoreData(new PanelStateData());
- colorMixer.setRestoreData(new PanelStateData());
- }
- }
Какие здесь плюсы?
- Можем общаться со всеми модулями одинаково.
- Получаем ошибки на этапе компиляции, если обращаемся ‘неправильно’ или ‘не к тому’ методу.
- Не ограничиваем модули одним предком.
- Разрешение ситуации, когда модули и панели уже написаны, а функционал сохранения их состояния необходимо добавить только сейчас.
Хочется упомянуть один момент. Понятное дело, что модули и панели редактора могут иметь и другой общий функционал - изменение размера, перемещение, привязка к другой панели. Тогда возможно появление желания сделать общий интерфейс для таких элементов, например, IEditorPanel, в котором определить все необходимые уважающей себя панели методы.
Стоит быть осторожными, так как это может в дальнейшем связать вам руки. Например, только нектором модулям необходимы методы getRestoreData и setRestoreData, но они включены в этот общий интерфейс, по которому происходит все общение системы с панелями. Тогда вы будете вынуждены определить эти методы во всех панелях, хоть и пустыми, что может привести к недоразумениям. А может случится так, что прийдется изменить сигнатуру какого-нибудь метода в интерфейсе, тогда вы будете вынуждены вносить изменения во все элементы, даже в те, где эти методы объявлены пустыми. Более гибким решением может быть использование нескольких интерфейсов, таких как IResizeable, IRelocatable и т. д.