组合guava eventbus和AWT Event线程处理的最佳方法

当你有一个异步事件总线和fire事件时,让我们说在UI中捕获的模型中你可能有以下问题:

已注册的处理程序在工作线程中执行,但所有UI swing更改都需要在AWT事件线程中执行。 这意味着您需要在EventQueue.invokeLater(...)包含所有处理程序clode。

这看起来像很多锅炉板代码。 我想知道是否有更智能的解决方案来解决这个问题。

guava事件总线的扩展如何标记在特殊线程中执行的处理程序? 这可以用annotion标记,例如@ExecuteWithinEDT

 class EventBusChangeRecorder { @Subscribe @ExecuteWithinEDT void recordCustomerChange(ChangeEvent e) { recordChange(e.getChange()); } } 

使用异步事件总线注册的处理程序在提供的Executor选择运行它们的任何线程上Executor ,而不一定是工作线程。

我所做的是创建了一个Executor的实现,它在事件队列线程上运行东西。 这很简单:

 public class EventQueueExecutor implements Executor { @Override public void execute(Runnable command) { EventQueue.invokeLater(command); } } 

然后,您可以使用以下方法创建EventBus

 EventBus eventBus = new AsyncEventBus(new EventQueueExecutor()); 

然后所有处理程序将在事件队列线程上执行。

编辑:

转发事件的示例:

 public class EventForwarder { private final EventBus uiEventBus; public EventForwarder(EventBus uiEventBus) { this.uiEventBus = uiEventBus; } // forward all events @Subscribe public void forwardEvent(Object event) { uiEventBus.post(event); } // or if you only want a specific type of event forwarded @Subscribe public void forwardEvent(UiEvent event) { uiEventBus.post(event); } } 

只需订阅您的主事件总线并将所有事件发布到主事件总线,但是将所有UI组件订阅到UI事件总线。

您可以创建仅在AWT线程上调度的EventBus:

 EventBus mybus = new AsyncEventBus("awt", new Executor() { public void execute (Runnable cmd) { if (EventQueue.isDispatchThread()) { cmd.run(); } else { EventQueue.invokeLater(cmd); } } });