Ответ 1
События в целом:
События всегда отправляются для информирования о чем-то (например, об изменении состояния). Позвольте взять ваш пример с мужчиной и стеной. Здесь мы можем представить себе, что есть игра, в которой пользователь может ходить как человек в лабиринте. Каждый раз, когда пользователь попадает в стену, он должен быть проинформирован о столкновении, чтобы он мог реагировать на него (например, стена может выступать как разрушенная стена). Это может быть достигнуто путем отправки события столкновения каждый раз при обнаружении столкновения со стеной. Это событие отправляется человеком, и каждый объект в системе, заинтересованный в событии, получает его и может реагировать на него соответствующим образом. Объекты, которые хотят получать события, должны регистрироваться как заинтересованные в событии.
Это то, как события работают вообще в каждой системе или структуре (не только в GWT). Чтобы отправлять и получать события в таких системах, вы должны определить:
- Что отправляется (как выглядят события)
- Кто получает события (приемники событий)
- Кто отправляет события (отправители событий)
Затем вы можете:
- Зарегистрировать приемники событий, которые хотят получать события.
- Отправить события
События в GWT:
Здесь я покажу пример использования пользовательских событий в GWT. Я буду использовать пример системы, которая отвечает за проверку почтового ящика и информирует пользователя о появлении новых писем. Предположим, что в системе имеется не менее двух компонент:
- контролер сообщений, ответственный за проверку почтового ящика и
- Дисплей сообщений, отвечающий за отображение новых писем
Контроллер сообщений отправляет события, когда полученная новая почта получена, и дисплей сообщений принимает эти события.
Шаг 1: Определение событий
Информация о новой почте будет отправлена как экземпляр класса MessageReceivedEvent
. Класс содержит новое письмо (для простоты пусть предположим, что это всего лишь String
).
Полный исходный код этого класса представлен ниже (комментарий для него ниже исходного кода).
public class MessageReceivedEvent extends GwtEvent<MessageReceivedEventHandler> {
public static Type<MessageReceivedEventHandler> TYPE = new Type<MessageReceivedEventHandler>();
private final String message;
public MessageReceivedEvent(String message) {
this.message = message;
}
@Override
public Type<MessageReceivedEventHandler> getAssociatedType() {
return TYPE;
}
@Override
protected void dispatch(MessageReceivedEventHandler handler) {
handler.onMessageReceived(this);
}
public String getMessage() {
return message;
}
}
MessageReceivedEventHandler
- это интерфейс, который представляет приемники событий. Не беспокойтесь об этом в данный момент, это будет обсуждаться позже.
Каждый класс, представляющий событие GWT, должен расширять класс GwtEvent
. Этот класс содержит два абстрактных метода, которые должны быть реализованы: getAssociatedType
и dispatch
. Однако в каждом классе событий они обычно реализуются очень похожим образом.
Класс хранит информацию о полученном сообщении (см. конструктор). Каждый приемник событий может получить его с помощью метода getMessage
.
Шаг 2: Определение приемников событий
Каждый тип события в GWT связан с интерфейсом, представляющим приемники этого типа события. В GWT приемники называются обработчиками. В примере интерфейс приемника событий для MessageReceivedEvent
будет называться MessageReceivedEventHandler
. Исходный код ниже:
public interface MessageReceivedEventHandler extends EventHandler {
void onMessageReceived(MessageReceivedEvent event);
}
Каждый обработчик должен расширять интерфейс EventHandler
. Он также должен определить метод, который будет вызываться при возникновении события (он должен принимать по крайней мере один параметр - событие). Здесь метод называется onMessageReceived
. Каждый приемник может реагировать на событие, реализуя этот метод.
Единственным приемником событий в этом примере является компонент MessageDisplayer
:
public class MessageDisplayer implements MessageReceivedEventHandler {
@Override
public void onMessageReceived(MessageReceivedEvent event) {
String newMessage = event.getMessage();
// display a new message
// ...
}
}
Шаг 3. Определение отправителей событий
В этом примере единственным отправителем события является компонент, ответственный за проверку почты - EventChecker
:
public class MessageChecker implements HasHandlers {
private HandlerManager handlerManager;
public MessageChecker() {
handlerManager = new HandlerManager(this);
}
@Override
public void fireEvent(GwtEvent<?> event) {
handlerManager.fireEvent(event);
}
public HandlerRegistration addMessageReceivedEventHandler(
MessageReceivedEventHandler handler) {
return handlerManager.addHandler(MessageReceivedEvent.TYPE, handler);
}
}
Каждый отправитель события должен реализовать интерфейс HasHandlers
.
Наиболее важным элементом здесь является поле HandlerManager
. В GWT HandlerManager
, поскольку имя предлагает управлять обработчиками событий (приемниками событий). Как было сказано в начале, каждый приемник событий, который хочет получать события, должен зарегистрироваться как заинтересованный. Для этого нужны менеджеры-обработчики. Они позволяют регистрировать обработчики событий, и они могут отправлять конкретное событие каждому зарегистрированному обработчику событий.
Когда создается HanlderManager
, он принимает один аргумент в своем конструкторе. Каждое событие имеет источник происхождения, и этот параметр будет использоваться в качестве источника для всех событий, отправляемых этим менеджером обработчика. В примере это this
, поскольку источником событий является MessageChecker
.
Метод fireEvent
определяется в интерфейсе HasHandlers
и отвечает за отправку событий. Как вы видите, он просто использует диспетчер обработчика для отправки (пожара) и события.
addMessageReceivedEventHandler
используется приемниками событий для регистрации в качестве заинтересованных в получении событий. Для этого используется диспетчер обработчиков.
Шаг 4: Принять приемники событий с отправителями событий
Когда все определено, приемники событий должны регистрироваться в отправителе событий. Обычно это делается при создании объектов:
MessageChecker checker = new MessageChecker();
MessageDisplayer displayer = new MessageDisplayer();
checker.addMessageReceivedEventHandler(displayer);
Теперь все события, отправленные checker
, будут получены displayer
.
Шаг 5: Отправить события
Чтобы отправить событие, MessageChecker
должен создать экземпляр события и отправить его с помощью метода fireEvent
. Это можно сделать в методе newMailReceived
:
public class MessageChecker implements HasHandlers {
// ... not important stuff omitted
public void newMailReceived() {
String mail = ""; // get a new mail from mailbox
MessageReceivedEvent event = new MessageReceivedEvent(mail);
fireEvent(event);
}
}
Я надеюсь, что это понятно и поможет:)