在Google Guava EventBusExplained页面中,我不明白他们何时说出以下内容:
侦听公共事件超类型(例如EventObject或 对象)...
...在传统的Java事件中:不容易。
...与EventBus: 事件会自动分派给任何超类型的侦听器, 允许侦听器使用接口类型或“通配符侦听器” 对象
答案 0 :(得分:6)
这与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
,这会变得非常简单。我在 GuavaIsAwesome
ComponentRepainter
类中需要的只是一种方法:
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);
这将在doSomething
上调用ComponentRepainter
方法,因为它不仅会将事件触发到@Subscribe
方法,而MouseEvent
方法也会参数,还会触发任何方法从MouseEvent
获得 assignable 的参数。换句话说,由于MouseEvent
延伸EventObject
,因此番石榴EventBus
会将其传递给接受EventObject
的任何内容。如果我们doSomething
接受Object
,那么我们就可以发送到EventBus
的每个事件,使其成为一种全局监听器(因为 Java中的所有扩展了Object
)。
同样适用于接口。如果将具体实现传递给某个接口的EventBus
,则将调用使用该接口的@Subscribe
方法(而不是具体类型)。它更加灵活,并且克服了“十种无用的方法”的方法。
答案 1 :(得分:3)
假设您有两个事件源:一个类型为FooEvent
的触发事件,另一个类型为BarEvent
的触发事件。假设FooEvent
和BarEvent
扩展了一个公共超类(或实现一个公共接口)MyEvent
。
使用EventBus,您可以收听MyEvent
类型的事件,并且会收到FooEvent
和BarEvent
的通知,因为它们都会扩展这个常见的超类型{{1 }}
如果您监听类型MyEvent
的事件,那么您将收到每个事件的通知,因为Java中的每个类都扩展了Object。那将是一个通配符监听器:它会监听所有内容。