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

0l3 23.12.2017 16:38

Централизованная обработка событий
 
Приветствую. Возник вопрос по централизованной обработке кастомных событий.

Свои события собираю в статику:
AppEvents.APP_EVENT_1 = "1"
AppEvents.APP_EVENT_2 = "2"

Структура программы типа "Звезда" - все события обрабатываются Контроллером:
Код:

        СубКласс6    СубКласс5
                      \  /
CубКласс1        -- Controller -- СубКласс4
                      /  \
        СубКласс2          СубКласс3

Для приема-передачи событий используется глобальный диспатчер (GlobalDispatcher). Субклассы используют его статический метод для отправки, Контроллер использует его для приема событий.

Вопрос: как в Контроллере не цеплять персональный слушатель для каждого app-события, а слушать любое из доступных в AppEvents-классе.
Код AS3:

//Соntroller
GlobalDispatcher.addEventListener(AppEvents.*, appEventManager);
..
..
private function appEventManager(e:AppEvents):void
        {
                swith(e):
                case "1": doSome1(); break;
                case "2": doSome2(); break;
                ..
        }

Выражение ругается
Код AS3:

AppEvents.*


ZergMaster 23.12.2017 18:01

А так разве можно?
По идее, то, что вы хотите, можно реализовать, передавая в общем событии AppEvents.APP_EVENT параметром идентификатор таргета.

Код AS3:

GlobalDispatcher.addEventListener(AppEvents.APP_EVENT, appEventManager);
..
..
private function appEventManager(event:AppEvents):void
        {
                swith(event.appId):
                case "1": doSome1(); break;
                case "2": doSome2(); break;
                ..
        }


caseyryan 23.12.2017 18:10

Цитата:

Вопрос: как в Контроллере не цеплять персональный слушатель для каждого app-события, а слушать любое из доступных в AppEvents-классе.
Код AS3:

//Соntroller
GlobalDispatcher.addEventListener(AppEvents.*, appEventManager);


Так сделать нельзя.
И вообще лучше не использовать вот таких глобальных диспетчеров

0l3 23.12.2017 18:46

Хорошо, если у меня десятки кастомных событий...

Код:

Пример "Изменение языка интерфейса":
  Вивер: [событие] Пользователь изменил язык интерфейса (комбобокс = "ru")
  Контроллер: Модель - загрузи файл ("ru")-языка локали!
  Модель: [событие-реакция] Файл локали загрузил. Данные в паблик-контейнере.
  Контроллер: Вивер - обнови UI! Используй такие данные (Модель.контейнерСтринговЛокали)
  Вивер: [событие-реакция] UI обновил успешно.

У Вивера десяток событий, у Модели десяток, и тд.. я уже представляю себе объявление 20-30 слушателей на Контроллере.. Как это обойти? Или сам подход такой организации общения между классами не правильный в данной ситуации. (caseyryan, я вас услышал=)

Wolsh 23.12.2017 20:14

Какое отношение Модель имеет к интерфейсу пользователя? О__о

Добавлено через 3 минуты
Ааа.. так это не MVC похоже... Тут зачем-то КОнтроллер слушает события Модели и вызывает методы Вью, то есть все шиворот-навыворот.

0l3 23.12.2017 21:51

Ок, неудачный пример мешает ответить на мой вопрос. Давайте еще проще..
Когда я говорю, что мне нужно, неважно зачем, прицепить на кнопку все маус-события вот так:
Код AS3:

button.addEventListener(MouseEvent.*, onMouseEvent)
...
function onMouseEvent(e:MouseEvent):void
{
  switch(e)
  {
    case MouseEvent.CLICK: doSome1();b;
    case MouseEvent.RIGHT_CLICK: doSome2();b;
  }
}

.. вы говорите, что в AS3 это сделать нельзя..

Wolsh 23.12.2017 22:10

Даже этот код неправильный, потому что e:MouseEvent, а в свитче у Вас switch(e), но case MouseEvent.CLICK (а это просто Стринг).
Попробую проще.
Такого синтаксиса не существует в принципе: MouseEvent.*
То есть вообще в языке нет такого.
То, что Вам хочется, решается очень просто и Вам уже объяснили, как.
То, что Вы пытаетесь заменить конструкцией MouseEvent.* — это просто строка. Это не событие, не его класс. Просто строка типа "click". Поэтому Вы смело можете диспатчить события ОДНОГО Типа ("тип" это как раз данная строка), но завести в своем AppEvents СВОЕ свойство, заменяющее Тип, например eventType:String, и задавать этот свой тип событиям перед диспатчем, а затем в свитче разбирать, что это пришло, не по event.type, а по своему event.eventType.
Так понятней?

0l3 23.12.2017 22:11

Благодарю.

Извиняюсь, не понял вот это:
Цитата:

Поэтому Вы смело можете диспатчить события ОДНОГО Типа ("тип" это как раз данная строка), но завести в своем AppEvents СВОЕ свойство, заменяющее Тип, например eventType:String, и задавать этот свой тип событиям перед диспатчем, а затем в свитче разбирать, что это пришло, не по event.type, а по своему event.eventType.
и это:
Цитата:

передавая в общем событии AppEvents.APP_EVENT параметром идентификатор таргета.
Если можно на примере разжевать..

Добавлено через 24 минуты
T.e тип сообщения будет всегда один APP_EVENT, на него я подписываюсь в Контроллере. Но при диспатче мне нужно дополнительно передавать, скажем еще 2 параметра - id источника сообщения и msg c названием события и уже e.id и e.msg проверять в swich'е?

Добавлено через 32 минуты
Дошло, спасибо =)

Wolsh 23.12.2017 22:53

Да не, не таргета. Хотя, в абстрактном смысле можно и так сказать. Имелось ввиду именно указатель, по которому можно идентифицировать что за событие, раз уж .type у всех одинаковый.

Вы подписываетесь на один Тип события — AppEvents.APP_EVENT. Это выражение — просто строковая константа, просто строка. Это может быть просто "а" например. Такой вот код будет работать
Код AS3:

fff.addEventListener("a", handlerA);
dispatchEvent(new AppEvents("a"));

То есть этот параметр type никак не связан с самим классом События. То, что принято его хранить в виде константы в классе События, это вопрос удобства и не более.
Тут надо понять только одну важную вещь: addEventListener() не интересуется, какого класса Событие надо "ловить". Его интересует только строка. Класс же События указывается только в приемнике обработчика, и если придет событие с типом "а", но не того класса, на который настроен обработчик, случится беда.
Итак, чтобы ловить ВСЕ события класса AppEvents, нужно подписаться на один тип и ловить их в обработчик, настроенный на AppEvents.
Но Вам же нужны РАЗНЫЕ типы событий, чтобы понимать что именно случилось. Эти же константы, которые Вы уже (видимо) завели в своем классе AppEvents, Вы можете использовать для другого свойства. Это свойство нужно ДОБАВИТЬ в класс события AppEvents.
Например, добавляем свойство eventType:
Код AS3:

public class AppEvents extends Event 
        {
                public var eventType:String;
                //... список констант //
                public function AppEvents(type:String, eventType:String, bubbles:Boolean=false, cancelable:Boolean=false)
                {
                        super(type, bubbles, cancelable);
                        this.eventType= eventType;
                }
 
                public override function clone():Event
                {
                        return new AppEvents(type, eventType, bubbles, cancelable);
                }
 
                public override function toString():String
                {
                        return formatToString("AppEvents", "type", "eventType", "bubbles", "cancelable", "eventPhase");
                }
 
        }

Теперь мы можем задавать характер события, не трогая родное свойство type (что позволит нам подписываться разом на все события AppEvents).
Код AS3:

addEventListener(AppEvents.APP_EVENT, hanlerAppEvents);
function handlerAppEvents(e:AppEvents):void { trace(e.eventType); }
//
dispatchEvent(new AppEvents(AppEvents.APP_EVENT, AppEvents.CHANGE_LANGUAGE));
dispatchEvent(new AppEvents(AppEvents.APP_EVENT, AppEvents.RESIZE_TOOLBAR));


0l3 23.12.2017 23:04

Да, так я себе это и понял. Еще раз спасибо за ваше терпение =)

Добавлено через 15 минут
Не понял еще:
Цитата:

Ааа.. так это не MVC похоже... Тут зачем-то КОнтроллер слушает события Модели и вызывает методы Вью, то есть все шиворот-навыворот.
..но это нужно почитать про MVC шаблоны.
В моем понимании Контроллер на то и К., чтобы дергать в нужный момент кого нужно, а остальные классы между собой не общаются на прямую.. это уменьшает количество взаимных связей, а умные книги говорят, что это хорошо =)


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

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