Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Java: Общие вопросы > Работа с событиями


Автор: Simplifier 27.4.2012, 16:25
Есть ли возможность и требуется ли в яве отписываться от отработавших слушателей?
В as3 принято всегда отписываться от слушателя события после того, как оно наступило. Например, если мы прослушиваем завершение загрузки некоторого объекта, то от этого события следует отписаться, как только загрузка будет завершена:
Код

package source{
    import flash.display.*;
    import flash.events.Event;
    import flash.net.URLRequest;
    import flash.system.LoaderContext;
    public class Content extends Sprite {
        private var loader:Loader = new Loader;
        private var request:URLRequest = new URLRequest;
        
        public function Content():void {
            //constructor
        }
        
        public function load(src:String):void {
            try {
                loader.close();
            }catch (e:Error) { }
            
            request.url = src;
            loader.load(request);
            //регистриуем слушатель completeHandler
            loader.contentLoaderInfo.addEventListener(Event.COMPLETE, completeHandler);
        }
        
        private function completeHandler(e:Event):void {
            //отписываемся от completeHandler`а
            loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, completeHandler);
            //обрабатываем загруженный объект доступный через loader.content
        }
    }
}

Дело в том, что если не отменять регистрацию слушателя после использования, то он так и останется висеть в оперативке, естественно, вместе со своим контекстом, ожидая повторного наступления события. Кроме того, сборщик мусора не удалит объект на котором подвешено событие, даже после того как занулишь все ссылки на этот объект. Вопрос, как обстоит с этим дело в java?

Автор: aleksandy 28.4.2012, 09:00
Возможность есть: SomeClass.removeXXXListener(XXXListener)

Не понимаю смысла подписывания на событие, если оно 100% одноразовое.

Автор: dorogoyIV 28.4.2012, 12:32
Цитата(Simplifier @  27.4.2012,  16:25 Найти цитируемый пост)
Дело в том, что если не отменять регистрацию слушателя после использования, то он так и останется висеть в оперативке, естественно, вместе со своим контекстом, ожидая повторного наступления события. Кроме того, сборщик мусора не удалит объект на котором подвешено событие, даже после того как занулишь все ссылки на этот объект. 

можно насчет этого не заморачиваться.
уже давно оперативка на компах не 32 Кб, а намного больше!

Автор: Simplifier 28.4.2012, 14:20
Спасибо) Протупил, действительно, надо было просто в хелп заглянуть и все) Просто когда учебник читал, не нашел, чтоб отписывание от обработчиков использовалось и не стал даже в доки заглядывать. А зря((
Цитата(aleksandy @ 28.4.2012,  09:00)

Не понимаю смысла подписывания на событие, если оно 100% одноразовое. 

В as3 события используются очень широко, там вообще нет блокирующих операций. Жизненный цикл всех сокетов, лоадеров, проигрывание аудио/видео и тд и тп отслеживается через события. Удобно, в общем-то) В яве события, по ходу, намного меньше распространены.
Цитата(dorogoyIV @ 28.4.2012,  12:32)

можно насчет этого не заморачиваться.
уже давно оперативка на компах не 32 Кб, а намного больше!

Ну эт да) Но такого ж мусора может до фига накопиться) Да и не только оперативка может забиваться, но и процессор. Если, например, создать несколько визуальных объектов и один таймер. И в каждом объекте подписаться на тиканье этого таймера. И, к примеру, при каждом такте менять координаты объекта. Если нам понадобится удалить один из этих объектов, мы удалим его со сцены, занулим на него ссылку и тд. А слушатель-то так и останется. И будет по прежнему отрабатывать каждый такт, изменяя координаты этого объекта. Ну, и потреблять ресурсы процессора.

Автор: Skynin 28.4.2012, 16:33
Цитата

Да и не только оперативка может забиваться, но и процессор.
...
А слушатель-то так и останется.
...
Ну, и потреблять ресурсы процессора.

Это да, флэша любит процессорное время сжирать, даже когда "ничего не делает".
У меня кулер на 4ядерном проце "голосом" сообщает - запустился где-то в браузере флеш! Как при конвертации видео, или в Alice Madness Return во время боя. В простое в Alice меньше шума чем от флеша.
А ноут - видать феном стать мечтает, когда с флешой сталкивается.
Так и не понял, почему программистам из Adobe не удается отлавливать "простой", а не гонять что-то в движке усиленно в цикле...

В Java слушатель мертвого объекта процессорного времени не потребляет. Да и живого, пока тот собственно не вызовет метод слушателя.

Правда, так как он содержит в себе ссылку на прослушиваемый объект, то тот не будет собран, пока не отпишешься от событий.
Или на него самого нет ссылки - то оба будут собран сборщиком мусора.
Всегда нужно помнить - слушатель держит в памяти того кого слушает, пока не отпишешься.

Цитата
В яве события, по ходу, намного меньше распространены.

потому что слушатель - это один из многих паттернов. И вовсе не универсальный и идеальный.
Но в системной библиотеке, и фреймворках вполне распространен.

Цитата
В as3 принято всегда отписываться от слушателя события после того, как оно наступило.

Действительно странный подход...

В java подписываются на события если нужно слушать многократно, регулярно, а не 1 раз.
А для одного раза есть и проще способы.

Автор: Simplifier 28.4.2012, 18:50
Цитата

Это да, флэша любит процессорное время сжирать, даже когда "ничего не делает".

Мм.. Нет, флеш во время простоя тоже не потребляет процессорное время. Видимо, вы говорите про флеш баннеры. Во-первых, баннеры обычно напиханы анимацией под завязку, а анимирование графики как раз потребляет немало процессора. Это не есть "ничего не делает". Во-вторых, их делают ни разу не программисты, а баннермейкеры, которых качество кода ни капли не заботит. Отсюда и результат. И, кстати, для экономии ресурсов рендеринг графики отключается через некоторое время, если вкладка с флешкой неактивна. http://habrahabr.ru/post/96180/
Цитата(Skynin @  28.4.2012,  16:33 Найти цитируемый пост)
Цитата
В as3 принято всегда отписываться от слушателя события после того, как оно наступило.

Действительно странный подход...

Почему странный? Я имел ввиду отписываться, когда событие уже больше не наступит или нам больше не нужно его перехватывать. Если мы, например, подвесили листенер на кнопку и нам надо, чтобы клик по ней обрабатывался все время пока запущена программа, то, конечно, отписываться незачем. А если, событие генерируется лишь конечное число раз, то после генерации последнего раза от него можно отписаться, так как пользы от него больше нет. Например, мы создали таймер, который после запуска сгенерирует событие 3 раза с интервалом 2 сек. После 3го такта мы от события отпишемся. (В as3 в этом случае после генерации 3х событий timer будет сгенерировано событие timerComplete, в котором удобно удалить регистрацию слушателя)

Цитата(Skynin @  28.4.2012,  16:33 Найти цитируемый пост)
В java подписываются на события если нужно слушать многократно, регулярно, а не 1 раз.
А для одного раза есть и проще способы.

Ну, другие способы, конечно, есть, но и подписывание на событие не назовешь сложным
Это в java работа событиями довольно сложна. Чтобы обработать событие, надо создать целый класс, который для разных событий должен реализовывать разные интерфейсы. С разным набором методов. Если нужны не все из этих методов, а только часть, то следует уже расширять класс-адаптер, а не интерфейс. И имена методов для регистрации разных типов событий тоже разные.
В as3 работа с событиями более стандартизирована и устроена проще. Чтобы зарегистрировать обработчик, его вместе с со строковым именем прослушиваемого события (и дополнительными необязательными параметрами, если требуется) передают методу со стандартным именем addEventListener. Для создания обработчика не надо писать отдельный класс, который что-то будет расширять. Так как в as3 можно передавать функции по ссылке, то листенер является методом, а не объектом. Единственное ограничение, налагаемое на листенер, состоит в том, что он принимает параметром объект события.

Автор: COVD 28.4.2012, 19:13
Цитата

Это в java работа событиями довольно сложна.... 

Очевидно, в других технологиях часть рутинной работы выполняется за сценой. Это упрощает программирование, но возможно маскирует суть. А суть "подписки" одна - в коллекцию добавляется обьект-лисенер. "Выписка" - из коллекции удаляется обьект-лисенер. Обьект-лисенер - это любой обьект с заранее известным методом. Не принципиально, обьект или ссылка на метод. Принципиально, что в коллекцию нечто однородного.

Автор: Simplifier 28.4.2012, 19:22
Ну, суть естественно одна. Никто не спорит) Единственное заметное различие в том, что в as3 в коллекцию вместо обьекта-лисенера добавляется метод-лисенер.

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)