我的问题与Guava EventBus dispatching完全相同,但是尽管基本问题相似,但尝试进行的修复使我陷入了黑暗。
我有2个事件被背对背触发。在完成所有处理程序后,第二个事件取决于第一个事件的最终状态。只有在第一个事件未取消的情况下,它才应触发。问题是这两个事件都是从另一个事件的处理程序中触发的。
因此,尽管我不在乎谁听第一嵌套事件,但我确实在乎他们要说些什么。我是否已经离开了事件和Guava的EventBus旨在解决的问题空间?
考虑:
public void parentEventHandler(ParentEvent parentEvent) {
Object nestedEvent = createNestedEvent();
eventBus.post(nestedEvent);
if(nestedEvent.isCancelled()) {
return;
}
Object anotherNestedEvent = createOtherNestedEvent();
eventBus.post(anotherNestedEvent);
}
我的期望:
1. parentEvent is posted
2. parentEventHandler is called
3. nestedEvent is posted
4. handlers of nestedEvent are called
5. finished handling nestedEvent
6. if statement checks for cancel state of nestedEvent
7. anotherNestedEvent is posted if nestedEvent not cancelled
8. handlers of anotherNestedEvent are called
9. finished handling anotherNestedEvent
10 finished handling parentEvent
怎么了:
1. parentEvent is posted
2. parentEventHandler is called
3. nestedEvent is posted
4. if statement checks for cancel state of nestedEvent (defaults to false)
5. anotherNestedEvent is posted
6. finished handing parentEvent
7. handlers of nestedEvent are called
8. nestedEvent is cancelled (too late now)
9. finished handling nestedEvent
10 handlers of anotherNestedEvent are called
11 finished handling anotherNestedEvent
在第8点处,无论处理程序是否取消该事件,由于取消检查默认为false,因此第二个事件已在队列中。番石榴的EventBus坚持在开始下一个事件之前完成其当前处理程序的运行,我确定它有其用途,但不是我想要的。
尝试入侵:
我注意到Guava有一个InstantDispatcher(https://github.com/google/guava/blob/master/guava/src/com/google/common/eventbus/Dispatcher.java#L179)的实现,该实现可以在事件发生时发布事件,这与保存事件的行为相反,直到默认PerThreadQueuedDispatcher(https://github.com/google/guava/blob/master/guava/src/com/google/common/eventbus/Dispatcher.java#L73)的所有订阅者都处理了当前事件为止。
但是,这些其他调度程序是程序包私有的,EventBus上没有公共API可以更改调度程序以使用。分叉Guava并将https://github.com/google/guava/blob/master/guava/src/com/google/common/eventbus/EventBus.java#L122和L136的默认调度程序更改为
Dispatcher.immediate()
,以另一个版本号在本地重新安装Guava,并且对该自定义构建进行大量修改,发现应用程序中的事件行为未更改所有。现在我完全迷路了。是否可以通过Guava的EventBus来实现严格的LIFO事件调度,或者我应该关注的是另一种范式,而不是可以取消事件并经常嵌套在其他事件处理程序中的有意义的事件?我不在乎有多少和哪些订户收听事件,但是我确实想知道他们对事件有何评论(即,他们是否决定取消事件)。该应用程序完全是单线程的。
最佳答案
如果您使用的是“常规” EventBus
,则可以通过创建辅助事件来使其正常工作。
添加接口InternalEventCallback
和类InternalEventCallbackHandler
:
interface InternalEventCallback {
void run();
}
class InternalEventCallbackHandler {
@Subscribe
public void internalEventHandler(InternalEventCallback r){
r.run();
}
}
在创建
EventBus
的位置,注册InternalEventCallbackHandler
:eventBus.register(new InternalEventCallbackHandler());
然后在您的
parentEventHandler
中执行:@Subscribe
public void parentEventHandler(ParentEvent parentEvent) {
NestedEvent nestedEvent = createNestedEvent();
eventBus.post(nestedEvent);
eventBus.post(new InternalEventCallback() {
@Override
public void run() {
if(nestedEvent.isCancelled()) {
return;
}
Object anotherNestedEvent = createOtherNestedEvent();
eventBus.post(anotherNestedEvent);
}
});
}
编辑:
如果将
AsyncEventBus
与“直接执行程序”一起使用,则可以得到与上例相同的行为,但是没有InternalEventCallback
和InternalEventCallbackHandler
EventBus eventBus = new AsyncEventBus(MoreExecutors.newDirectExecutorService());