Жизненный цикл Spark компонентов Flex фреймворка и базовые правила наследования компонентов

Для правильной работы со Spark компонентами и создания собственных компонентов, необходимо иметь понятие о том, как и по каким правилам они работают. Сегодня мы  рассмотрим базовые принципы, без знания которых невозможно эффективно использовать этот мощный фреймворк.

Итак, жизненный цикл каждого компонента во Flex фреймворке проходит следующие этапы:

  • создание (construction);
  • конфигурация (configuration);
  • подключение/присоединение (attachment);
  • инициализация (initialization);
  • инвалидация (invalidation);
  • взаимодействие (interaction);
  • удаление (detachment);
  • сборка мусора (garbage collection).


При наследовании компонентов разработчик может (должен) переопределять следующие методы:

  • createChildren();
  • commitProperties();
  • measure();
  • updateDisplayList().

Когда мы добавляем компонент с помощью mxml разметки

происходит следующее.

Сначала запускается этап создания, и инстанциируется экземпляр класса MyComponent. Затем происходит конфигурация, в течение которой компоненту выставляются свойства и стили, объявленные при добавлении компонента (применяются они позже). Пока внутри компонента не доступны свойства systemManager, stage, root и т.д. Но при этом могут вызываться get/set методы (конфигурация), поэтому при реализации необходимо правильно определять такие методы. Нельзя сразу применять изменения внутри метода, необходимо использовать валидацию.

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

Фазы инициализации:

  • устанавливается значение свойства parent;
  • событие «preinitialize»;
  • создание дочерних компонентов createChildren() (для скинируемых компонентов это порождает вызов attachSkin(), про скины мы поговорим в следующий раз);
  • событие «initialize», вызов метода инициализации initialize().

При переопределении метода createChildren() в наследниках, необходимо создавать здесь постоянные дочерние компоненты (которые должны проходить этапы создания, конфигурации и подключения), но не применять динамических изменений (это будет происходить на этапе валидации). Вызывать super.createChildren() лучше в конце переопределения.

После того как компонент инициализирован, наступает этап инвалидации. Компоненты Flex фреймворка используют отложенную валидацию изменений. Аналогично как мы делали выше с полем data: изменения сохраняются и помечаются как измененные, а валидация происходи позже. Это позволяется сохранить высокую производительность, в том числе за счет того, что изменения применяются не по одному, а сразу все. Чтобы сообщить флексу о том, что требуется валидация, необходимо вызывать один из методов инвалидации:

  • изменение свойств — invalidateProperties();
  • изменение размеров — invalidateSize();
  • изменение отображения — invalidateDisplayList().

Для применения изменения свойств будет вызван метод commitProperties(), именно его и надо переопределять в наследниках для применения изменения данных. Для определения необходимости обновления используются флаги (_dataChanged в примере с set data).

Отметим, что, так как валидация происходит после инициализации, то в методе commitProperties() уже доступны дочерние элементы, созданные в createChildren().

При валидации размеров будет вызван метод measure(), который устанавливает предпочтительные размеры (поля measuredWidth, measuredHeight, measuredMinWidth, measuredMinHeight). Вызов метода может быть пропущен, если метод canSkipMeasurement() возвращает true. По умолчанию он вернет true, если установлены explicitWidth и explicitHeight (значения, присвоенные пользователем: <s:Label width="100"/>), но в наследниках это поведение может быть переопределено (например условие отличается у наследников GroupBase, Skin и т.д.). Пример:

Валидация размеров может вызвать инвалидацию display list’а (если размер изменился), что приведёт к вызову метода updateDisplayList(). При переоределении этого метода в наследниках здесь следует позиционировать и устанавливать размеры дочерних элементов. Также можно перерисовывать например фон. Актуальный размер компонента выставляется именно здесь. Вызов super.updateDisplayList() снова советую делать в конце переопределения.

По окончании первого полного цикла инвалидации рассылается событие «creationComplete», после чего компонент находится в рабочем состоянии и доступен для взаимодействия с ним.

Когда компонент уже не нужен — он удаляется со сцены (методами удаления или выставлением флага visible=false). Если при этом больше не существует ссылки на объект или она слабая, то компонент будет удален из памяти сборщиком мусора. Обратите внимание, что ссылки на объект могут сохраняться при использовании обработчиков событий, биндига, сохранении в качестве ключей в словаре и т.д., поэтому не забывайте отписываться от событий, если больше не требуется его слушать.

Полезные ссылки

Добавить комментарий