GWT自定义事件

Cia*_*rán 67 events gwt

嘿,我有一个问题让我了解自定义GWT事件处理程序的工作方式.我已经阅读了很多关于这个主题的内容,它仍然是一些有雾的东西.我已经在Stackoverflow上读取了这个GWT自定义事件处理程序的线程.有人可以在应用的mannar中解释它,如下所示.

我有2个班级和一个班级.当男人与块碰撞时,man会触发一个事件(onCollision())然后块类会侦听该事件.

谢谢

Pio*_*otr 196

一般事件:

始终发送事件以通知某事(例如,状态的改变).让我们以一个男人和一面墙为例.在这里,我们可以想象有一个游戏,用户可以在迷宫中作为一个人走路.每当用户撞到墙壁时,应该通知碰撞,以便它可以对其作出反应(例如,墙壁可以使其自身成为被破坏的墙壁).这可以通过每次检测到与墙壁的碰撞时发送碰撞事件来实现.该事件由一个人发送,并且对该事件感兴趣的系统中的每个对象都接收它并且可以相应地对其做出反应.想要接收事件的对象必须将自己注册为对事件感兴趣.

这就是事件在每个系统或框架中的一般工作方式(不仅仅是在GWT中).要在此类系统中发送和接收事件,您必须定义:

  1. 发送了什么(事件是什么样的)
  2. 谁接收事件(事件接收者)
  3. 谁发送事件(事件发件人)

然后你可以:

  1. 注册想要接收事件的事件接收器
  2. 发送活动

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

MessageReceivedEventHandler是一个表示事件接收器的接口.暂时不要理会,这将在后面讨论.

表示GWT事件的每个类都必须扩展GwtEvent类.该类包含两个必须实现的抽象方法:getAssociatedTypedispatch.然而,在每个事件类中,它们通常以非常类似的方式实现.

该类存储有关已接收消息的信息(请参阅构造函数).每个事件接收器都可以使用getMessage方法获取它.

第2步:定义事件接收器

GWT中的每个事件类型都与表示此事件类型的接收者的接口相关联.在GWT中,接收器称为处理程序.在该示例中,MessageReceivedEvent将命名事件接收器接口MessageReceivedEventHandler.源代码如下:

public interface MessageReceivedEventHandler extends EventHandler {
    void onMessageReceived(MessageReceivedEvent event);
}
Run Code Online (Sandbox Code Playgroud)

每个处理程序都必须扩展EventHandler接口.它还应该定义一个在事件发生时将被调用的方法(它应该至少需要一个参数 - 一个事件).这里的方法是命名的onMessageReceived.每个接收器都可以通过实现此方法对事件做出反应.

示例中唯一的事件接收器是MessageDisplayer组件:

public class MessageDisplayer implements MessageReceivedEventHandler {

    @Override
    public void onMessageReceived(MessageReceivedEvent event) {
        String newMessage = event.getMessage();
        // display a new message
        // ...
    }

}
Run Code Online (Sandbox Code Playgroud)

第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);
    }

}
Run Code Online (Sandbox Code Playgroud)

每个事件发送者都必须实现HasHandlers接口.

这里最重要的元素是一个HandlerManager领域.在GWT HandlerManager中,名称建议管理事件处理程序(事件接收器).正如在开始时所说的那样,每个想要接收事件的事件接收者必须将自己注册为感兴趣的.这就是处理程序管理器的用途.它们可以注册事件处理程序,并且可以将特定事件发送到每个已注册的事件处理程序.

HanlderManager创建a时,它的构造函数中需要一个参数.每个事件都有一个原始源,此参数将用作此处理程序管理器发送的所有事件的源.在示例中,它是this事件的来源MessageChecker.

该方法fireEventHasHandlers接口中定义,负责发送事件.正如您所看到的,它只是使用处理程序管理器来发送(fire)和事件.

addMessageReceivedEventHandler事件接收器使用它来将自己注册为对接收事件感兴趣.再次使用处理程序管理器.

第4步:使用事件发件人绑定事件接收器

当一切都被定义时,事件接收者必须在事件发送者中注册自己.这通常在创建对象期间完成:

MessageChecker checker = new MessageChecker();
MessageDisplayer displayer = new MessageDisplayer();
checker.addMessageReceivedEventHandler(displayer);
Run Code Online (Sandbox Code Playgroud)

现在发送的所有事件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);
    }

}
Run Code Online (Sandbox Code Playgroud)

我希望它很清楚,并会有所帮助:)

  • 非常感谢您的回复.我将不得不阅读几次,但我很确定我现在得到它.非常清晰,写得很好.感谢您抽出宝贵时间回答我的问题. (7认同)
  • 顺便说一下,目前HandlerManager类被标记为已弃用,建议使用SimpleEventBus代替. (7认同)
  • 是的,在GWT 2.1.1中,最好用EventBus替换HandlerManager (4认同)

Hil*_*amp 35

由于这个问题和Piotr GWT的答案增加了对创建自定义事件的略微不同的支持.此事件实现是特定的构建,与程序包中的GWT的EventBus一起使用com.google.web.bindery.event.shared.关于如何为GWT 2.4构建自定义事件的示例:

import com.google.web.bindery.event.shared.Event;
import com.google.web.bindery.event.shared.EventBus;
import com.google.web.bindery.event.shared.HandlerRegistration;

/**
 * Here is a custom event. For comparison this is also a MessageReceivedEvent.
 * This event extends the Event from the web.bindery package.
 */
public class MessageReceivedEvent extends Event<MessageReceivedEvent.Handler> {

    /**
     * Implemented by methods that handle MessageReceivedEvent events.
     */
    public interface Handler {
        /**
         * Called when an {@link MessageReceivedEvent} event is fired.
         * The name of this method is whatever you want it.
         *
         * @param event an {@link MessageReceivedEvent} instance
         */
        void onMessageReceived(MessageReceivedEvent event);
    }

    private static final Type<MessageReceivedEvent.Handler> TYPE =
        new Type<MessageReceivedEvent.Handler>();

    /**
     * Register a handler for MessageReceivedEvent events on the eventbus.
     * 
     * @param eventBus the {@link EventBus}
     * @param handler an {@link MessageReceivedEvent.Handler} instance
     * @return an {@link HandlerRegistration} instance
     */
    public static HandlerRegistration register(EventBus eventBus,
        MessageReceivedEvent.Handler handler) {
      return eventBus.addHandler(TYPE, handler);
    }    

    private final String message;

    public MessageReceivedEvent(String message) {
        this.message = message;
    }

    @Override
    public Type<MessageReceivedEvent.Handler> getAssociatedType() {
        return TYPE;
    }

    public String getMessage() {
        return message;
    }

    @Override
    protected void dispatch(Handler handler) {
        handler.onMessageReceived(this);
    }
}
Run Code Online (Sandbox Code Playgroud)

该事件使用如下:

要使用eventbus注册此事件的处理程序,请调用MessageReceivedEvent类上的静态寄存器方法:

MessageReceivedEvent.register(eventbus, new MessageReceivedEvent.Handler() {
   public void onMessageReceived(MessageReceivedEvent event) {
     //...do something usefull with the message: event.getMessage();
   }
});
Run Code Online (Sandbox Code Playgroud)

现在fireEvent使用新构造的事件在事件总线调用上触发事件:

eventBus.fireEvent(new MessageReceivedEvent("my message"));
Run Code Online (Sandbox Code Playgroud)

另一个实现可以在GWT自己的EntityProxyChange事件类中找到.该实现使用EventBus的替代选项.它使用能够添加绑定到特定源的处理程序,addHandlerToSource并且可以通过它来触发eventBus.fireEventFromSource.

在使用GWT的活动时,此处给出的事件实现也更合适.

  • 感谢更新的GWT 2.4代码.你能说明在注册处理程序和解雇事件时如何获得对eventBus的引用? (3认同)