Просмотр полной версии : Централизованная обработка событий
Приветствую. Возник вопрос по централизованной обработке кастомных событий.
Свои события собираю в статику:
AppEvents.APP_EVENT_1 = "1"
AppEvents.APP_EVENT_2 = "2"
Структура программы типа "Звезда" - все события обрабатываются Контроллером:
СубКласс6 СубКласс5
\ /
CубКласс1 -- Controller -- СубКласс4
/ \
СубКласс2 СубКласс3
Для приема-передачи событий используется глобальный диспатчер (GlobalDispatcher). Субклассы используют его статический метод для отправки, Контроллер использует его для приема событий.
Вопрос: как в Контроллере не цеплять персональный слушатель для каждого app-события, а слушать любое из доступных в AppEvents-классе.
//Соntroller
GlobalDispatcher.addEventListener(AppEvents.*, appEventManager);
..
..
private function appEventManager(e:AppEvents):void
{
swith(e):
case "1": doSome1(); break;
case "2": doSome2(); break;
..
}
Выражение ругается AppEvents.*
ZergMaster
23.12.2017, 18:01
А так разве можно?
По идее, то, что вы хотите, можно реализовать, передавая в общем событии AppEvents.APP_EVENT параметром идентификатор таргета.
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-классе.
//Соntroller
GlobalDispatcher.addEventListener(AppEvents.*, appEventManager);
Так сделать нельзя.
И вообще лучше не использовать вот таких глобальных диспетчеров
Хорошо, если у меня десятки кастомных событий...
Пример "Изменение языка интерфейса":
Вивер: [событие] Пользователь изменил язык интерфейса (комбобокс = "ru")
Контроллер: Модель - загрузи файл ("ru")-языка локали!
Модель: [событие-реакция] Файл локали загрузил. Данные в паблик-контейнере.
Контроллер: Вивер - обнови UI! Используй такие данные (Модель.контейнерСтринговЛокали)
Вивер: [событие-реакция] UI обновил успешно.
У Вивера десяток событий, у Модели десяток, и тд.. я уже представляю себе объявление 20-30 слушателей на Контроллере.. Как это обойти? Или сам подход такой организации общения между классами не правильный в данной ситуации. (caseyryan, я вас услышал=)
Какое отношение Модель имеет к интерфейсу пользователя? О__о
Добавлено через 3 минуты
Ааа.. так это не MVC похоже... Тут зачем-то КОнтроллер слушает события Модели и вызывает методы Вью, то есть все шиворот-навыворот.
Ок, неудачный пример мешает ответить на мой вопрос. Давайте еще проще..
Когда я говорю, что мне нужно, неважно зачем, прицепить на кнопку все маус-события вот так:
button.addEventListener(MouseEvent.*, onMouseEvent)
...
function onMouseEvent(e:MouseEvent):void
{
switch(e)
{
case MouseEvent.CLICK: doSome1();b;
case MouseEvent.RIGHT_CLICK: doSome2();b;
}
}
.. вы говорите, что в AS3 это сделать нельзя..
Даже этот код неправильный, потому что e:MouseEvent, а в свитче у Вас switch(e), но case MouseEvent.CLICK (а это просто Стринг).
Попробую проще.
Такого синтаксиса не существует в принципе: MouseEvent.*
То есть вообще в языке нет такого.
То, что Вам хочется, решается очень просто и Вам уже объяснили, как.
То, что Вы пытаетесь заменить конструкцией MouseEvent.* — это просто строка. Это не событие, не его класс. Просто строка типа "click". Поэтому Вы смело можете диспатчить события ОДНОГО Типа ("тип" это как раз данная строка), но завести в своем AppEvents СВОЕ свойство, заменяющее Тип, например eventType:String, и задавать этот свой тип событиям перед диспатчем, а затем в свитче разбирать, что это пришло, не по event.type, а по своему event.eventType.
Так понятней?
Благодарю.
Извиняюсь, не понял вот это:
Поэтому Вы смело можете диспатчить события ОДНОГО Типа ("тип" это как раз данная строка), но завести в своем 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 минуты
Дошло, спасибо =)
Да не, не таргета. Хотя, в абстрактном смысле можно и так сказать. Имелось ввиду именно указатель, по которому можно идентифицировать что за событие, раз уж .type у всех одинаковый.
Вы подписываетесь на один Тип события — AppEvents.APP_EVENT. Это выражение — просто строковая константа, просто строка. Это может быть просто "а" например. Такой вот код будет работать
fff.addEventListener("a", handlerA);
dispatchEvent(new AppEvents("a"));То есть этот параметр type никак не связан с самим классом События. То, что принято его хранить в виде константы в классе События, это вопрос удобства и не более.
Тут надо понять только одну важную вещь: addEventListener() не интересуется, какого класса Событие надо "ловить". Его интересует только строка. Класс же События указывается только в приемнике обработчика, и если придет событие с типом "а", но не того класса, на который настроен обработчик, случится беда.
Итак, чтобы ловить ВСЕ события класса AppEvents, нужно подписаться на один тип и ловить их в обработчик, настроенный на AppEvents.
Но Вам же нужны РАЗНЫЕ типы событий, чтобы понимать что именно случилось. Эти же константы, которые Вы уже (видимо) завели в своем классе AppEvents, Вы можете использовать для другого свойства. Это свойство нужно ДОБАВИТЬ в класс события AppEvents.
Например, добавляем свойство eventType:
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).
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));
Да, так я себе это и понял. Еще раз спасибо за ваше терпение =)
Добавлено через 15 минут
Не понял еще:
Ааа.. так это не MVC похоже... Тут зачем-то КОнтроллер слушает события Модели и вызывает методы Вью, то есть все шиворот-навыворот.
..но это нужно почитать про MVC шаблоны.
В моем понимании Контроллер на то и К., чтобы дергать в нужный момент кого нужно, а остальные классы между собой не общаются на прямую.. это уменьшает количество взаимных связей, а умные книги говорят, что это хорошо =)
Ну вообще-то Контроллер не контролёр в троллейбусе, чтобы "дергать кого нужно".
Контроллер это микросхема, обеспечивающая перевод сигналов датчиков на понятный системе язык.
Контроллер клавиатуры определяет, какие клавиши нажаты/отпущены и извещает об этом систему.
Контроллер мыши определяет, в каком направлении мышь двигается и переводит это в числа в системе координат.
Ни тот ни другой не работает "в обратную сторону": компьютер не может заставить ползать по столу мышку, а клавиатуру — нажимать клавиши.
Здесь было уже достаточно холиваров на тему MVC и роль контроллера и да, я конечно слышал о таких схемах, где контроллер берет на себя и связь от Модели к Вью. Но в классическом кошерном MVC такого нет, ибо это бессмыслица. Вы в любом случае пишете Вью для конкретной модели, потому что задача Вью — отображать свойства Модели. Вью может быть не привязана к Модели только в том случае, если Вью это какой-то маленький модуль GUI для отображения одного свойства (например, прогрессбар). Ему неважно, откуда это свойство приходит. Поэтому никаким "Вью" он попросту не является и может быть использован безо всякого MVC где угодно. В MVC же Вью подписывается на события Модели и сама забирает нужные ей свойства, для этого не нужен Контроллер. Вью имеет ссылку на Модель, потому что она заточена показывать свойства этой Модели. Контроллер же нужен именно для разделения В и М в плане управления Моделью, поскольку Вью является не только изображением на мониторе, но и устройством ввода — клавиатурой и мышью, или тач-скрином. То есть — источником данных для Модели, и управляющих запросов пользователя. И вот этот хаос необходимо контролировать и переводить на понятный Модели язык. Контроллер обеспечивает логику взаимодействия и безопасность данных Модели, не позволяя Вьюхе дергать ее методы напрямую.
Работает на vBulletin ® версия 3.7.3. Copyright ©2000-2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Copyright © 1999-2008 Flasher.ru. All rights reserved.