Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   Отписывание от событий (http://www.flasher.ru/forum/showthread.php?t=174650)

s3dworld 30.01.2012 13:35

Отписывание от событий
 
Всем доброго дня!

Всё таки довольно таки странный вопрос, но мне хочется как бы всё по правильному. Вот обычный код для каждой программы:

Код AS3:

package 
{
        import flash.display.MovieClip;
        import flash.events.Event;
 
        public class main extends MovieClip
        {
                public function main()
                {
                        if(stage)
                                Start();
                        else
                                addEventListener(Event.ADDED_TO_STAGE,OnAddedToStage);
                }
 
                private function OnAddedToStage(_event:Event):void
                {
                        removeEventListener(Event.ADDED_TO_STAGE,OnAddedToStage);
                        Start();
                }
 
                private function Start():void
                {
 
                }
 
        }
 
}

Вроде всё понятно. Такой пример я видел много раз. В некоторых же примерах встречал вот так:

Код AS3:

package 
{
        import flash.display.MovieClip;
        import flash.events.Event;
 
        public class main extends MovieClip
        {
                public function main()
                {
                        if(stage)
                                Start();
                        else
                                addEventListener(Event.ADDED_TO_STAGE,OnAddedToStage);
                }
 
                private function OnAddedToStage(_event:Event):void
                {
                        Start();
                }
 
                private function Start():void
                {
 
                }
 
        }
 
}

То есть особо не уделяется внимания освобождению прослушки. Я же пишу вот так:

Код AS3:

package 
{
        import flash.display.MovieClip;
        import flash.events.Event;
 
        public class main extends MovieClip
        {
                private var isAddedToStageListener:Boolean=false;
 
                public function main()
                {
                        if(stage)
                        {
                                Start();
                        }
                        else
                        {
                                isAddedToStageListener=true;
                                addEventListener(Event.ADDED_TO_STAGE,OnAddedToStage);
                        }
                }
 
                private function OnAddedToStage(_event:Event):void
                {
                        if(isAddedToStageListener) removeEventListener(Event.ADDED_TO_STAGE,OnAddedToStage);
 
                        Start();
                }
 
                private function Start():void
                {
 
                }
 
        }
 
}

Для меня конечно мой вариант правильный, так как он сам подписывает и сам отписывает (но выглядит не очень красиво). Как вообще стоит писать? Просто будет ли Flash сам отписывать события или же многие спустя рукава на всё это смотрят?

TanaTiX 30.01.2012 13:41

Используйте мягкие ссылки, названия методов - с маленькой буквы.
Какая необходимость в использовании метода Start?

s3dworld 30.01.2012 13:45

TanaTiX
Цитата:

Используйте мягкие ссылки
Что за мягкие ссылки? Впервые слышу.

Цитата:

названия методов - с маленькой буквы
Ну это на самом деле дело стиля. Я уже выработал свой стиль работая на C++, так что я уже привык.

Цитата:

Какая необходимость в использовании метода Start?
Так ведь не всегда вызовется функция OnAddedToStage(), то есть stage может быть уже получен (точнее клип в него добавлен). Следовательно какой смысл дублировать код в OnAddedToStage() и до него, если можно всё в одну функцию вынести?

Stitch512 30.01.2012 13:49

А в чем смысл флажка isAddedToStageListener? Отписываемся если он true, но если false то по коду OnAddedToStage и не придет...

s3dworld 30.01.2012 13:54

Stitch512
Согласен! Упустил из виду. Тут значит проблем нет. Раз вызвалась, значит подписывались и всегда можно отписывать. Косяк мой.

Тогда у меня 3 вопроса:

1. Что за мягкие ссылки?
2. Можно ли отписывать событие, если оно не было подписано (что вообще будет?)
3. delete используется для удаления полей в динамическом классе, а можно ли как-то удалить сам динамический класс из памяти (я конечно понимаю что он сам удалится со временем если на него нет ссылок, но а самом можно?)?

in4core 30.01.2012 14:22

Цитата:

2. Можно ли отписывать событие, если оно не было подписано (что вообще будет?)
Ничего не будет, ни кому не помешает :) тоесть проверки делать не надо в вашем случае
Цитата:

3. delete используется для удаления полей в динамическом классе, а можно ли как-то удалить сам динамический класс из памяти (я конечно понимаю что он сам удалится со временем если на него нет ссылок, но а самом можно?)?
Только GC может его снести , когда придет время, если ссылки убиты, в дебаге же можно запускать ГЦ вручную вроде, но зачем ?:)

ProxyGreen 30.01.2012 14:25

Под мягкими ссылками видимо имеется ввиду параметр "useWeakReference" в методе:
addEventListener(Event.ADDED, listener, false, 0, true);
GC вроде как не учитывает слабые ссылки и по своему усмотрению может удалить завалявшийся слушатель. Но здесь не подходящий случай имхо.

Dukobpa3 30.01.2012 14:32

>> 1. Что за мягкие ссылки?
Код AS3:

addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, <b>useWeakReference:Boolean = trueb>):void

>> 2. Можно ли отписывать событие, если оно не было подписано (что вообще будет?)
Код AS3:

hasEventListener(type:String):Boolean
// Проверяет, имеет ли объект EventDispatcher прослушиватели, зарегистрированные для определенного типа события.

>> 3. delete используется для удаления полей в динамическом классе, а можно ли как-то удалить сам динамический класс из памяти (я конечно понимаю что он сам удалится со временем если на него нет ссылок, но а самом можно?)?
Ну это не плюсы, тут виртуальная машина всё решает. Всё что мы можем сделать это занулить все ссылки на объект дабы повысить вероятность очистки. Вручную сборщик мусора запускать не рекомендуется.

справка

TanaTiX 30.01.2012 14:33

Цитата:

Ну это на самом деле дело стиля. Я уже выработал свой стиль работая на C++, так что я уже привык.
В действительности есть некие соглашения, принятые во флеш-сообществе. К тому же так рекомендует адоб. Писал бы я на С++, старался бы писать с большой, но это флеш. Программа от этого иначе работать не будет, а вот коллеги не поймут, будут лишние вопросы и пр.
Цитата:

Так ведь не всегда вызовется функция OnAddedToStage(), то есть stage может быть уже получен (точнее клип в него добавлен). Следовательно какой смысл дублировать код в OnAddedToStage() и до него, если можно всё в одну функцию вынести?
По указанному коду функция всегда вызывается вначале работы экземпляра класса, т.е. по сути при добавлении на сцену. Почему тогда все ее содержимое не поместить в onAddedToStage? Хотя соглашусь, что бывают ситуации, когда нужно разделять.
На остальное вроде ответили.

Добавлено через 1 минуту
Dukobpa3, по 2-му пункту согласен с in4core

expl 30.01.2012 14:41

Люди, откуда такая мантра: "не отписался от события - утекла память".
Подписка подразумевает, что мы создаем ссылку на слушатель внутри dispatcher-a. Если dispatcher и владелец слушателя - одно и то же лицо - память никуда не потечёт.

Самый простой эксперимент - создаем класс-наследник Sprite, внутри вешаем trace на ENTER_FRAME в конструкторе. Создаем этот класс и удаляем на него ссылки. Наблюдаем некоторое время приход трейсов. Запускаем GC - трейсы пропали.
В принципе, можно даже просто подписаться на спрайт и не создавать на него ссылок нигде - то же самое будет (он на нас ссылается, а мы на него - нет).

Но от ENTER_FRAME как раз надо отписываться - ибо нефиг процессор грузить пока до тебя GC добирается.

А вешаться на события на мягких ссылках не стоит по одной причине:
- все время, пока GС будет добираться до объекта - объект будет исправно обрабатывать события - грузить проц тобишь.


Часовой пояс GMT +4, время: 14:03.

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.