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

时间:2012-11-16 23:53:58

标签: java guava

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

  

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

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

2 个答案:

答案 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的触发事件。假设FooEventBarEvent扩展了一个公共超类(或实现一个公共接口)MyEvent

使用EventBus,您可以收听MyEvent类型的事件,并且会收到FooEventBarEvent的通知,因为它们都会扩展这个常见的超类型{{1 }}

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