Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   Удаление объектов в АС3 (http://www.flasher.ru/forum/showthread.php?t=126668)

giir 24.06.2009 15:12

Удаление объектов в АС3
 
Насколько я знаю объекты в АС3 удаляются так же как в java, т.е. когда на объект не остается ссылок он автоматом удаляется.
Так вот у меня возникла небольшая проблема. Код, конечно, гораздо сложнее, но отразить самую суть приведу лишь кусок:
Код AS3:

// MovieClip добавляется в stage (General.getStage() - возвращает stage)
// Diver - наследуется от мувиклипа
General.getStage().addChild(new Diver());
 
// Hero  - наследуется от мувиклипа
General.getStage().addChild(new Hero());
...
// В классе Diver при опр. условиях устанавливаем статическую переменную Hero.enemy
Hero.enemy=this;
 
// В классе Hero при опр. условиях удаляем из детей у stage объект типа Diver и зануляем ссылку Hero.enemy
if(Hero.enemy!=null){
  if (Hero.enemy.parent != null) {
    Hero.enemy.parent.removeChild(Hero.enemy);
    Hero.enemy = null;
  }
}

Казалось бы - объект Diver должен удалится если и не совсем,то уж по крайтей мере из детей stage точно!
Ан нет... срабатывает Diver.onEnterFrame()...

Коллеги, подскажите, пожалуйста что я делаю не так... ну или если мой код совсем не поймете, то хотябы просто объясните как удалить объект совсем, чтобы не срабатывало у instance не срабатывало событие Event.ENTER_FRAME.

Заранее спасибо!!!

Gal4enochek 24.06.2009 15:21

Даже если вы удалили объект, листнер на Event.ENTER_FRAME, который вы к нему прикрепили, все равно останется. Во такая вот фича.
Так что для объектов, которым вы цепляли листнеры нужно определять деструктор, который их потом буду удалять.
Например
Код AS3:

public class Hero extends MovieClip{
  //...
  // код вашего класса
  // ....
  public function destroy():void{
        if (this.willTriger(Event.ENTER_FRAME))
            this.removeEventListener(Event.ENTER_FRAME, ваш_обработчик);
  } 
}

И тогда перед удаление вызывать деструктор.

2morrowMan 24.06.2009 16:15

Цитата:

Сообщение от giir (Сообщение 830389)
т.е. когда на объект не остается ссылок он автоматом удаляется.

Это не так. Он удаляется не автоматом, не пулеметом. Удаляет объект Garbage Collector и не обязательно сразу же, после того как на объект не остается ссылок.

dimarik 24.06.2009 16:33

Цитата:

Сообщение от Gal4enochek (Сообщение 830394)
Код AS3:

if (this.willTriger(Event.ENTER_FRAME)) {
    this.removeEventListener(Event.ENTER_FRAME, ваш_обработчик);
}


Gal4enochek, я хотел уточнить, с чем связана проверка this.willTriger(Event.ENTER_FRAME, ваш_обработчик) на наличие слушателя заданного события в цепочке родителей этого this в иерархии display list'а? Если this не слушает такое событие, а, предположим, его parent это делает, то проверка вернет true. Теперь Вы удаляете [this.ваш_обработчик] как несуществующий слушатель. Хорошо, что эксепшн не генерируется для removeEventListener.

Gal4enochek 24.06.2009 17:01

dimarik, наверное я действительно ошиблась. В таких случаях нужно использовать hasEventListener()? Или вообще без проверок можно обойтись?

giir 24.06.2009 17:06

Вообще непонятное творится.. в ролике fla объявлен класс General как Document Class.
Из его конструктора последовательно вызываются др. конструкторы, которые добавляются на stage после создания.. т.е.
Код AS3:

stage.addChild(new BaseEnemy())

в конструкторе для BaseEnemy вываливаю логи. Запускаю ролик и судя по логам к своему великому удивлению замечаю, что конструктор BaseEnemy() запускается периодично все время.
Может кто знает :
1) Означает ли это что создается новый инстанс типа BaseEnemy или просто вызывается сам метод.
2) Как от этого избавится, очень надо, чтобы new BaseEnemy вызвалось 1 раз.

PS: спасибо за removeEventListener хотя пока и не помогло, но кое-что прояснилось - 100% в будущем бы на это напоролся...

dimarik 24.06.2009 17:11

Цитата:

Сообщение от Gal4enochek (Сообщение 830435)
dimarik, наверное я действительно ошиблась. В таких случаях нужно использовать hasEventListener()? Или вообще без проверок можно обойтись?

Можно и hasEventListener, и без проверок. Эксепшн-то не генерится.
И да, если Вы обращаетесь к методам родительских классов, то лучше употреблять словечко super. Сразу все понятно, что метод где-то выше в цепочке наследования.

Код AS3:

if ( super.hasEventListener(Event.ENTER_FRAME) ) {
    super.removeEventListener(Event.ENTER_FRAME, this.handler_eneterFrame);
}


silin 24.06.2009 18:45

почти официальный запуск GC, правда только для 10-ки
Код AS3:

package  silin.utils
{
        import flash.display.Loader;
        import flash.events.Event;
        import flash.utils.ByteArray;
 
        /**
        * утитилита для принудительного вызова GC за счет 10-чного unloadAndStop<br>
        *: грузим-выгружаем, походу запускается GC
        * @author silin
        */

        public class GCForcer
        {
                private static const LOADER:Loader = new Loader();
                private static const GIF:Array = [
                        71, 73, 70, 56, 57, 97, 1, 0, 1, 0, -128, 0, 0, -1, -1, -1, 0, 0, 0, 33, -7,
                        4, 0, 7, 0, -1, 0, 44, 0, 0, 0, 0, 1, 0, 1, 0, 0, 2, 2, 68, 1, 0, 59
                ];
 
                public function GCForcer()
                {
                        trace ("GCForcer is a static class and should not be instantiated.");
                }
 
                public static function force():void
                {
 
                        LOADER.contentLoaderInfo.addEventListener(Event.COMPLETE, loaderComplteteHandler);
 
                        var ba:ByteArray = new ByteArray();
                        for (var i:int = 0; i < GIF.length; i++)
                        {
                                ba.writeByte(GIF[i]);
                        }
 
                        LOADER.loadBytes(ba);
                }
 
                static private function loaderComplteteHandler(evnt:Event):void
                {
                        LOADER.contentLoaderInfo.removeEventListener(Event.COMPLETE, loaderComplteteHandler);
                        try
                        {
                                LOADER.unloadAndStop();
                        }catch (err:Error) { };
 
                }
 
        }
}

тест:
Код AS3:

package 
{
        import flash.display.Sprite;
        import flash.events.*;
        import silin.utils.GCForcer;
 
 
        public class Main extends Sprite
        {
 
                private var _test:Sprite = new Sprite();
                private var _counter:int = 0;
 
                public function Main():void
                {
                        if (stage) init();
                        else addEventListener(Event.ADDED_TO_STAGE, init);
 
                }
 
                private function init(e:Event = null):void
                {
                        removeEventListener(Event.ADDED_TO_STAGE, init);
                        _test.addEventListener(Event.ENTER_FRAME, testEnterFrameHandler);
                        //смотрим по клику
                        stage.addEventListener(MouseEvent.CLICK, stageClickHandler);
 
                }
 
                private function testEnterFrameHandler(evnt:Event):void
                {
                        _counter++;
                        trace( "_counter : " + _counter );
                }
 
                private function stageClickHandler(evnt:MouseEvent):void
                {
 
                        _test = null;
                        //без вызова GCForcer.force трейс в testEnterFrameHandler продолжит работать неопределенно долго
                        GCForcer.force();//вызов unloadAndStop
                }
 
        }
 
}


2morrowMan 24.06.2009 21:03

Цитата:

Сообщение от dimarik (Сообщение 830441)
И да, если Вы обращаетесь к методам родительских классов, то лучше употреблять словечко super. Сразу все понятно, что метод где-то выше в цепочке наследования.

Все и так понятно. Это ненужный выпендреж и/или попытка писать по "умному". Употребляя super там где не надо можно только усложнить себе разработку. Только не спрашивайте почему.

Добавлено через 1 минуту
silin, циферки в константе GIF что-то значат ? :)

Felicast 24.06.2009 21:11

Цитата:

Сообщение от 2morrowMan (Сообщение 830494)
silin, циферки в константе GIF что-то значат ? :)

судя по всему - это что-то вроде empty.gif
чтобы не загружать с сервера находится прямо во флэшке. прикольное решение


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

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