![]() |
|
||||||||||
|
|||||||
|
|
« Предыдущая тема | Следующая тема » |
| Опции темы | Опции просмотра |
|
![]() |
![]() |
|
|||||
|
Регистрация: Oct 2013
Сообщений: 126
|
Прошу помочь советом.
Дело в том, что у меня, наверное, обоснованное, но всё же параноидальное стремление удалять объекты и слушатели, которые больше не нужны. Архитекрута моего проекта такова: Main хранит "уровни" и контролирует переход между ними. Уровни - это объекты Sprite с соответствующими детьми (надписями, кнопками, объектами и т.д.). Переход из уровня 1 в уровень 2 представляет собой удаление со сцены уровня 1 и помещение туда уровня 2. При этом необходимо удалить не только сам уровень 1 со всеми его слушателями, но и всех его детей и внуков с их слушателями. К сожалению, функции "удалить всю семью со слушателями на всех уровнях ниже вызываемого объекта", откликающуюся на removed_from_stage, я не нашёл (подозреваю, что такой и нет), поэтому делаю так: При создании любого объекта, которому предстоит иметь детей, я ставлю проверку события removed_from_stage, и в cleanup() удаляю всех его слушателей при помощи removeEventListener, а также всех детей при помощи . Соответственно, при удалении уровня 1 удаляются его дети, которые при своём удалении удаляют своих детей и т.д. И все удаляют своих слушателей. Но при этом получается, что такую "чистилку" приходится приписывать каждому объекту, ведь даже при использовании удаляются только дети, а "внуки" либо остаются, либо от потери родителя начинают выдавать ошибки. Прошу прощения за корявое объяснение, но по-другому не смог( В книгах написано, что ненужные слушатели и объекты надо удалять. Но неужели для этого надо каждому объекту добавлять слушателя removed_from_stage, чтобы он "почистился" сам и заставил "почиститься" своих детей? По большому счёту вопрос заключается в том, как это делать правильно, т.е. "как лучше чистить детей и слушателей"? |
|
|||||
|
Если удалить ссылку на "корневой" объект, содержащий в себе ссылки на другие объекты (и никто из-вне на них ссылки не имеет), то GC заберет все это скопом без лишних слов вне зависимости, какая там иерархия ссылочной вложенности. От событий надо отписываться в таком случае только у таймеров и enterFrame, чтобы зря не отрабатывали, пока GC сподобится прийти.
__________________
тут я |
|
|||||
|
КорДум,
Таймер и дисплей объекты являются наследниками EventDispatcher. Соответственно, ссылки подписчиков они хранят сами в себе. Дисплей объект, находящийся на сцене, перед отрисовкой получает событие enterFrame. Это происходит, когда внешний код проверяет, есть ли у него подписки и высылает событие. В случае удаления объекта со сцены, про его подписчиков никто не знает, кроме самого объекта, а значит, удалять его подписчиков не обязательно. С таймером похожая ситуация, удалять подписчиков не обязательно. Важно - останавливать таймер для удаления.
__________________
Дети не должны знать о своих родителях |
|
|||||
|
Регистрация: Oct 2013
Сообщений: 126
|
правильно ли я понимаю, что если при удалении "главного родителя" удалить всех его детей, и следующей же строкой запустить
, то все "потомки" этого "главного родителя" вместе со слушателями будут уничтожены?
|
|
|||||
|
Цитата:
С таймером попроще, он не дисплей объект и не может находиться в неком нативном списке. Пока таймер запущен и тикает, флеш плеер имеет на него собственную внутреннюю ссылку или что-то вроде того. В запущенном состояний, такой таймер не удалится никогда. Что-бы удалить, его надо обязательно остановить. Затем, как обычно обнулить ссылки, ссылающиеся на него. Однако, не обязательно отписывать подписчиков на этот таймер, так как всю информацию о своих подписчиках таймер хранит только в себе. (EventDispatcher)
__________________
Дети не должны знать о своих родителях |
|
|||||
|
Tails, ок, я думал, что чего-то не понимаю. Я говорил про объект, который подписан на событие таймера, не про сам таймер. На самом деле мы недопоняли друг друга =)
Добавлено через 8 минут a7s1h1, Цитата:
__________________
тут я |
|
|||||
|
Главное, что мы поняли друг-друга
![]() a7s1h1, Удалять внуков не обязательно, если вы удаляете их родителя, в котором они лежат. Главное, что-бы на этих внуков ещё кто-то не ссылался, кроме их родителя. КорДум вам уже это посоветовал. Удалять подписчиков можно и нужно, особенно если вы не на 100% понимаете весь замут с этими диспетчерами. Вы так-же можете использовать при подписке - "слабые ссылки", которые не препятствуют удалению объекта, если на него больше никто другой не ссылается. System.gc() Работает только в дебаговом режиме, (нужно для отладки). В релизной версий, вы никак не можете самостоятельно вызвать или повлиять на gc. Ваша главная задача для удаления - не оставлять ссылок, исключением могут быть только "слабые ссылки".
__________________
Дети не должны знать о своих родителях |
|
|||||
|
Регистрация: Oct 2013
Сообщений: 126
|
я, возможно, не так понял, но у меня при удалении "главным родителем" всех своих детей "внуки" никуда не пропадают, толькое если их не уничтожит сам родитель. Другими словами,
Объект 1 - родитель для объекта 2 Объект 2 - родитель для объекта 3 При удалении объектом 1 всех своих детей объект 3 по-прежнему остаётся. А при повторном создании объекта 2 у него вместо одного ребёнка становится уже 2 (проверял через trace(numChildren)) Причём, я проверил, на некоторые их неудалённых детей больше никто не ссылался. Слабые ссылки я ещё не пробовал, но теперь это уже не главная проблема. Если я не смогу вызывать System.gc() в релизе, значит на него вообще не имеет смысла расчитывать в плане чистки в нужные мне моменты? Я совсем запутался. Поможет ли для чистки такой подход: В каждом классе, подлежащем помещению на сцену, писать: package { import flash.display.Sprite; import flash.events.Event; public class ClassName extends Sprite { // свойства child:Object; // какой-то объект-ребёнок // Контсруктор public function ClassName() { addEventListener(Event.ADDED_TO_STAGE, init); } private function init(e:Event):void { removeEventListener(Event.ADDED_TO_STAGE, init); addEventListener(Event.REMOVED_TO_STAGE, cleanup); // добавляем детей child = new Child(); addChild(child); // добавляем слушателей детям (при необходимости) child.addEventListener(Event.ENTER_FRAME,childupdate) // добавляем слушателей себе addEventListener(Event.ENTER_FRAME,update) } private function cleanup(e:Event):void { // удаляем слушателей детей child.removeEventListener(Event.ENTER_FRAME,update) // удаляем детей while (numChildren > 0) { removeChildAt(0) }; // удаляем своих слушателей removeEventListener(Event.ENTER_FRAME,update) removeEventListener(Event.REMOVED_TO_STAGE, cleanup); } private function update():void { // }; private function childupdate():void { // }; } } |
|
|||||
|
Создайте в родительском конструкторе столько детей, сколько вам нужно.
Добавьте их в родителя: Подпишитесь в конструкторе на обновление, если вам необходимо: Тут переудалять детей или переотписываться от события нет необходимости, так-как все ссылки содержит родительский класс ClassName. Если кто-то создать ClassName и добавит его на сцену, он создаст своих детей и будет обновляться. Если ClassName кто-то удалит, GC автоматически заберёт его и всё его содержимое, так-как кроме ClassName, о нём больше никто и ничего не знает.
__________________
Дети не должны знать о своих родителях |
![]() |
![]() |
Часовой пояс GMT +4, время: 19:36. |
|
|
« Предыдущая тема | Следующая тема » |
|
|