Почему слушатели моего мероприятия стреляют не раз? - PullRequest
1 голос
/ 14 июня 2010

В моем проекте Flash у меня есть мувиклип, который имеет 2 ключевых кадра. Оба кадра содержат по одному мувиклипу каждый.

кадр 1 - Landing
кадр 2 - Game

Ход выполнения приложения прост:

  1. Пользователь заходит на целевую страницу (кадр 1)
  2. Пользователь нажимает кнопку «начать игру»
  3. Пользователь выводится на страницу игры (кадр 2)
  4. Когда игра заканчивается, пользователь может нажать кнопку «повторить игру», которая возвращает его к шагу 1

Оба ролика Landing и Game связаны с отдельными классами, определяющими прослушиватели событий. Проблема в том, что, когда я возвращаюсь к шагу 1 после игры, слушатели события Game запускаются дважды для их соответствующего события. И если я прохожу процесс в третий раз, слушатели событий запускаются три раза для каждого события. Это продолжает происходить, поэтому, если я перебираю поток приложения 7 раз, слушатели событий запускаются семь раз. Я не понимаю, почему это происходит, потому что в кадре 1 мувиклип Game (и я бы предположил, что связанный с ним экземпляр класса) не существует - но я явно что-то здесь упускаю.

Я столкнулся с этой проблемой и в других проектах и ​​попытался исправить ее, сначала проверив, существуют ли прослушиватели событий, и определив их только в том случае, если их нет, но в итоге я получил неожиданные результаты, которые на самом деле не помогли. проблема.

Мне нужно убедиться, что слушатели событий запускаются только один раз. Любой совет и понимание будет принята с благодарностью, спасибо!

Ответы [ 2 ]

2 голосов
/ 14 июня 2010

Не видя код или не зная, какие события вы слушаете, и кто / что их запускает, довольно сложно узнать наверняка.

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

Простой подход к видеоклипам и другим экранным объектам, который достаточно хорош, заключается в прослушивании событий ADDED_TO_STAGE и REMOVED_FROM_STAGE. Идея здесь в том, что ваш объект «активируется», когда он добавляется на сцену, что в вашем случае будет, когда вы достигнете кадра 2 для своего класса Game; он «деактивируется» при удалении, то есть при возврате к кадру 1.

Что-то в этом роде:

public class Game extends MovieClip {

    private var _timer:Timer;

    public function Game() {
        addEventListener(Event.ADDED_TO_STAGE,init);
        addEventListener(Event.REMOVED_FROM_STAGE,destroy);
    }

    private function init():void {
        //  your init code goes here
        //  just an example:
        _timer = new Timer(33);
        _timer.addEventListener(TimerEvent.TIMER,mainLoop);
        _timer.start();
        trace("init");
    }

    private function destroy():void {
        _timer.stop();
        _timer.removeEventListener(TimerEvent.TIMER,mainLoop);
        trace("destroy");
    }

    private function mainLoop(e:TimerEvent):void {
        //  code for main loop here...
        trace("mainLoop");
    }
}

Проверьте следы, чтобы увидеть, работает ли он правильно. Вы должны увидеть трассировку «init», затем «mainLoop», пока вы остаетесь в кадре 2, и «destroy», когда возвращаетесь к кадру 1. «mainLoop» должен прекратить трассировку в этой точке.

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

2 голосов
/ 14 июня 2010

Если у вас есть два кадра с разными клипами на одном слое, каждый раз, когда этот кадр «входит», этот клип создается. Когда он «уходит», клип удаляется, но он все равно будет храниться и не будет собирать мусор. Поэтому в следующий раз, когда кадр входит в другой клип, он «создается» и получает своего собственного слушателя. Лучше всего удалить слушателей, когда вы меняете кадры. Я обычно обхожусь вокруг такого рода вещей, имея слушателя за Event.REMOVED_FROM_STAGE в каждом классе. Если он удален, вы очищаете оставшихся слушателей.

Вы также можете поэкспериментировать со «слабыми слушателями»:

addEventListener(GameEvent.GAME_START, gameStartedHandler, false, 0, true);

Значение "true" делает ссылку "слабой", поэтому, если объект удален, сборщик мусора может его забрать. Я бы не стал полностью полагаться на это. Лучше удалить ссылки вручную, чтобы быть уверенным.

Этот ответ предполагает, конечно, многое. Было бы полезно, если бы вы разместили код / ​​скриншоты / флеш для лучшей диагностики.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...