Форум 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=172587)

enepx 13.12.2011 14:06

Корректное удаления экземпляра из памяти
 
Привет всем.
Простая ситуация: есть объект, в конструкторе создается кнопка, подписывается на MouseEvent.CLICK. Потом экземпляр этого объекта удаляется (removeChild) с родителя. Нужно ли отписать кнопку от MouseEvent.CLICK для корректного удаления из памяти?
Спасибо.

Inet_PC 13.12.2011 14:07

Да нужно.

enepx 13.12.2011 14:08

Знатоки говорят точно надо, сам стараюсь так и делать всегда, но может именно тут зря?
Удаление подписки за "внешние" объекты на обсуждается, вопрос именно о внутренних объектах класса.
Спасибо.

gloomyBrain 13.12.2011 14:13

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

Inet_PC 13.12.2011 14:15

Цитата:

но может именно тут зря?
Никогда не зря, плюс чистая совесть.
Цитата:

Удаление подписки за "внешние" объекты на обсуждается, вопрос именно о внутренних объектах класса.
А какая разница?

Добавлено через 31 секунду
Опоздал

smithy 13.12.2011 14:21

В некоторых случаях можно использовать weakReference=true:
Код AS3:

_button.addEventListener( MouseEvent.CLICK, onClick, false, 0, true )

При сборке мусора такой листенер не будет являться ссылкой на объект.

enepx 13.12.2011 14:25

Это я все знаю и использую. Вопрос в целесообразности удаления подписки на объект, который является ребенком и "убивается" автоматически при "убийстве" родителя.

goodguy 13.12.2011 15:10

Он не убивается, если на него есть ссылки. Это покажет любой профайлер.

in4core 13.12.2011 15:13

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

i.o. 13.12.2011 15:15

Цитата:

Слушатель клика не грузит память
Ок, пруф в студию.

Inet_PC 13.12.2011 15:24

На тормоз в автомобиле жать
Цитата:

не обязательно совершенно
ибо бензин рано или поздно кончится.
Цитата:

Слушатель клика не грузит память
еще как отводится. ED хранит эту инфу в своих дербях, а раз хранит значит и память на это расходуется.
Код AS3:

кастомЭвент, который может произойти от чего угодно

Кто мне запретит 1000-ми рассылать самому MouseEvent ? И все кто подписаны будут их ловить.

gloomyBrain 13.12.2011 17:36

Цитата:

и даже не кастомЭвент, который может произойти от чего угодно
Сезон тупняков на flasher.ru продолжается...

fish_r 13.12.2011 17:55

Цитата:

Сообщение от gloomyBrain (Сообщение 1051182)
Сезон тупняков на flasher.ru продолжается...

))


тем, не менее, где-то здесь @etc (могу ошибаться, но кажется все-таки @etc) писал, что не обязательно отписывать слушателей внутренних событий в удаляемом объекте... тоже о чём то народ спорил...

Но, я всё равно отписываю всех слушателей - так, на всякий случай, в порядке армейского ... а

Можно проверить профайлером, это вроде не сложно.

ChuwY 13.12.2011 20:31

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

Вот пример (смотрите в приложении):
Классы Level0-1-2-3 -- наследники спрайта с пустым телом.

Код AS3:

package {
  import flash.display.DisplayObject;
  import flash.display.DisplayObjectContainer;
  import flash.display.Sprite;
  import flash.utils.getDefinitionByName;
  import flash.utils.setTimeout;
 
  Level0;
  Level1;
  Level2;
  Level3;
  public class DOCTest extends Sprite {
    public static const MAX_DEEP : int = 3;
    public static const WIDTH : int = 10;
    public function DOCTest() {
      fill(0, this);
      setTimeout(easyClear, 5000);
      //setTimeout(fullClear, 5000, this);
    }
 
    private function fill(deep : int, container : DisplayObjectContainer):void{
      for(var i : int = 0; i < WIDTH; i++){
        var DOCLASS : Class = getDefinitionByName("Level"+deep) as Class;
        var DO : DisplayObjectContainer = new DOCLASS();
        trace("DO = " + DO);
        container.addChild(DO);
        if(deep < MAX_DEEP){
          fill(deep+1,DO);
        }
      }
 
    }
 
    private function easyClear():void{
      while(numChildren){
        removeChildAt(0);
      }
    }
 
    private function fullClear(container : DisplayObjectContainer):void{
      while(container.numChildren){
        var DOC: DisplayObjectContainer = container.removeChildAt(0) as DisplayObjectContainer;
        if(DOC){
          fullClear(DOC);
        }
      } 
    }
  }
}

При использовании функции, которая удаляет только объекты верхнего уровня получаем такой снимок:
http://*************/s/1oHmT -- если в памяти повис объект нулевого уровня, то тащит за собой цепочку детей.

А если рекурсивно разделить все от всего, то вот такой (который тоже не идеален. почему -- увы, не знаю, надеюсь, кто-нибудь объяснит)
http://*************/s/1oHkQ

Так что очистить все слушатели, задеструктить и занулить все, до чего дотянешься -- святое дело каждого.


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

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