Показать сообщение отдельно
Старый 06.05.2011, 12:56
dimarik вне форума Посмотреть профиль Отправить личное сообщение для dimarik Найти все сообщения от dimarik
  № 3  
Ответить с цитированием
dimarik
.
 
Аватар для dimarik

модератор форума
Регистрация: Sep 2003
Адрес: Москва
Сообщений: 4,630
Записей в блоге: 20
Если из списка отображения (Display List, DL) удаляется узел, то все иерархически связанные с ним дети, внуки и правнуки и т.д. удалятся (будут garbage collected) при условии отсутствия ссылок на объекты этой ветки из внешних объектов.

Если, например, хотя бы один объект в ветке будет подписан на события Stage, то вся ветка будет жить.
Каким образом?

Предположим, что контейнер (условно, Depth_0) находится в списке отображения, содержит одного ребенка (Depth_1) и тот подписан на события мыши от Stage. Ребенок в свою очередь имеет другого ребенка (Depth_2). Метод-хендлер объекта Depth_1 зарегистрирован в качестве приемника события MouseEvent в Stage (Depth_1 исполнил код super.stage.addEventListener(MouseEvent.CLICK, this.handler_click)). Ссылка на этот метод (handler_click) находится во внутреннем массиве (Array) _listeners объекта Stage. Теперь удаляем Depth_0 из DL. Ни один уважающий себя (Garbage Collector, GC) при таком раскладе не удалит объект Depth_1. Итак, Depth_1 будет жить.

Как же будет жить его родитель (Depth_0)? У ребенка есть ссылка на родителя в поле parent. Родитель будет жить.

Как будет жить Depth_2 -- дитя Depth_1? У Depth_1 есть список детей и ссылка на Depth_2 находится в этом списке.


Для каждого объекта можно добавлять слушатель Event.REMOVED с проверкой на event.eventPhase === AT_TARGET или event.target === event.currentTarget. Это означает, что ребенок лишился своего непосредственного родителя. При выполнении одного из этих условий можно освобождать слушателей ребенка во внешних вещателях.

Если хендлер и источник -- находятся в одном и том же объекте, то иногда можно не отписываться от самого себя же. События, генерируемые действиями пользователя, такие как взаимодействие с мышью, клавиатурой, при потере фокуса (следствие удаления объекта из DL), и некоторые внутренние (Event.RENDER), перестанут генерироваться. Остальные внутренние события: ENTER_FRAME, EXIT_FRAME, FRAME_CONSTRUCTED, ACTIVATE, DEACTIVATE продолжат генерироваться до момента срабатывания GC.


Недостатком отписки от событий по REMOVED_FROM_STAGE является следующее: если мы захотим переместить ветку дисплей объектов на другой узел, последует лавинообразное удаление слушателей, а затем их добавление. Ведь при перемещении ветки происходит последовательное её удаление из DL, а затем добавление в DL. Cработают все её слушатели события REMOVED_FROM_STAGE и ADDED_TO_STAGE.

Недостатком отписки от событий по Event.REMOVED следует признать необходимость по-объектного удаления детей сверху вниз, от кроны к корню.
__________________
Воспитан в TimeZero. Работаю в Mail.ru.