Guava EventBus:监听事件超类型(如EventObject或Object)意味着什么



在Google Guava EventBusExplained页面中,我不明白他们什么时候说:

侦听常见事件超类型(如EventObject或对象)
。。。在传统Java事件中:这并不容易。
。。。使用EventBus:事件被自动分派给任何超类型的侦听器,允许接口类型的侦听器或的"通配符侦听器"对象

  1. 侦听公共事件超类型意味着什么
  2. 当他们提到EventObject时,他们是在谈论java.util.EventObject吗
  3. 允许"接口类型的侦听器或对象的通配符侦听器"意味着什么

这与方法重载和Guava的EventBus类可以克服的接口的限制有关。

对于接口,请考虑以下场景:

我有相同的代码,可以为多种形式的输入调用。例如,侦听鼠标事件、键事件和焦点事件的侦听器,但所有方法都做相同的事情:重新绘制源。这意味着我的代码将是这样的:

public class BunchOfListeners implements MouseListener, KeyListener, FocusListener {
@Override
public void focusGained(FocusEvent e) {
doSomething(e);
}
@Override
public void focusLost(FocusEvent e) {
doSomething(e);
}
@Override
public void keyTyped(KeyEvent e) {
doSomething(e);
}
@Override
public void keyPressed(KeyEvent e) {
doSomething(e);
}
@Override
public void keyReleased(KeyEvent e) {
doSomething(e);
}
@Override
public void mouseClicked(MouseEvent e) {
doSomething(e);
}
@Override
public void mousePressed(MouseEvent e) {
doSomething(e);
}
@Override
public void mouseReleased(MouseEvent e) {
doSomething(e);
}
@Override
public void mouseEntered(MouseEvent e) {
doSomething(e);
}
@Override
public void mouseExited(MouseEvent e) {
doSomething(e);
}
public void doSomething(EventObject e) {
((Component) e.getSource()).repaint();
}
}

注意到这有多难看吗?有10种不同的方法,当我们最终唯一关心的是从事件中获取源(顺便说一句,这是由EventObject指定的,这就是他们在示例中使用它的原因),并对其调用repaint

有了Guava的EventBus,这变得超级简单。在GuavaIsAwesomeComponentRepainter类中,我只需要一个方法:

public class ComponentRepainter {
@Subscribe
public void doSomething(EventObject e) {
((Component) e.getSource()).repaint();
}
}

当你用EventBus注册它,然后在上面发射MouseEvent时:

EventBus eventBus = ... ;
eventBus.register(new ComponentRepainter());

后来:

MouseEvent e = ... ;
eventBus.post(e);

这将调用ComponentRepainter上的doSomething方法,因为它不仅会将事件激发到参数为MouseEvent@Subscribe方法,还会激发到具有可从MouseEvent分配的参数的任何方法。换句话说,因为MouseEvent扩展了EventObject,Guava的EventBus将把它传递给任何接受EventObject的对象。如果我们让doSomething接受Object,那么我们可以获得发布到EventBus的每个事件的,使其成为一种全局侦听器(因为Java中的everything扩展了Object)。

同样的事情也适用于接口。如果将某个接口的具体实现传递给EventBus,则将调用使用该接口(而不是具体类型)的@Subscribe方法。它更加灵活,并克服了"10种无用方法"的方法。

假设您有两个事件源:一个是类型为FooEvent的激发事件,另一个是BarEvent的激发事件。假设FooEventBarEvent扩展了一个公共超类(或实现了一个通用接口)MyEvent

使用EventBus,您可以侦听类型为MyEvent的事件,并且会收到FooEvents和BarEvents的通知,因为它们都扩展了这种常见的超类型MyEvent

如果您监听java.lang.Object类型的事件,那么您将收到每个事件的通知,因为Java中的每个类都扩展了Object。这将是一个通配符侦听器:它侦听所有内容。

最新更新