3

Google Guava EventBusExplained页面中,当他们说以下内容时,我不明白:

侦听一个常见的事件超类型(例如 EventObject 或 Object)...
...在传统的 Java 事件中:不容易。
...使用 EventBus:事件会自动分派给任何超类型的侦听器,允许接口类型的侦听器或 Object 的“通配符侦听器”。

  1. 监听一个常见的事件超类型是什么意思?
  2. 当他们提到 EventObject 时,他们是在谈论 java.util.EventObject 吗?
  3. 允许“接口类型的侦听器或对象的“通配符侦听器”是什么意思?
4

2 回答 2

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's 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的参数的任何方法。换句话说,因为MouseEventextends EventObject,番石榴EventBus会将它传递给任何接受的东西EventObject。如果我们doSomething接受了Object,那么我们可以获取发布到的每个EventBus事件,使其成为一种全局侦听器(因为Java 中的所有内容都Object扩展了)。

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

于 2012-11-17T00:23:36.850 回答
3

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

使用 EventBus,您可以监听 type 的事件MyEvent,并且您会收到FooEvents 和BarEvents 的通知,因为它们都扩展了这个公共超类型MyEvent

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

于 2012-11-17T00:08:06.373 回答