Google Web Toolkit (GWT) EventBus 事件触发/处理
背景故事:
我正在开发一个 GWT 应用程序,使用标准 MVP 设计模式,还使用 RPC 从我的自定义数据处理 servlet 获取数据(在幕后做了很多工作)。不管怎样,我的目标是创建一个非常简单的自定义缓存机制,将从 RPC 回调返回的数据存储在静态缓存 POJO 中。 (回调还使用 SimpleEventBus 向所有注册的处理程序发送自定义事件。)然后,当我再次请求数据时,我将在再次执行 RPC 服务器调用之前检查缓存。 (还可以使用 EventBus 发送自定义事件)。
问题:
当我从 RPC 回调发送事件时,一切正常。问题是,当我只发送缓存的对象时,在 RPC 回调之外发送事件。由于某种原因,此事件没有到达我注册的处理程序。这是一些代码:
public void callServer(final Object source)
{
if(cachedResponse != null)
{
System.err.println("Getting Response from Cache for: "+ source.getClass().getName());
//Does this actually fire the event?
eventBus.fireEventFromSource(new ResponseEvent(cachedResponse),source);
}
else
{
System.err.println("Getting Response from Server for: "+ source.getClass().getName());
service.callServer(new AsyncCallback<String>(){
@Override
public void onFailure(Throwable caught) {
System.err.println("RPC Call Failed.");
}
@Override
public void onSuccess(String result) {
cachedResponse = result;
eventBus.fireEventFromSource(new ResponseEvent(cachedResponse),source);
}
});
}
}
现在我有两个活动,HelloActivity 和 GoodbyeActivity(取自:GWT MVP 代码)
当调用处理程序时,它们还会打印出消息。无论如何,这是我从日志中得到的输出:(不正确)
从缓存中获取响应:com.hellomvp.client.activity.HelloActivity GoodbyeActivity 中的响应来自:com.hellomvp.client.activity.HelloActivity 从缓存获取响应:com.hellomvp.client.activity.GoodbyeActivity HelloActivity 中的响应来自:com.hellomvp.client.activity.GoodbyeActivity
我期望得到的是这样的:
Getting Response from Cache for: com.hellomvp.client.activity.HelloActivity
Response in HelloActivity from: com.hellomvp.client.activity.HelloActivity
Getting Response from Cache for: com.hellomvp.client.activity.GoodbyeActivity
Response in GoodbyeActivity from: com.hellomvp.client.activity.GoodbyeActivity
如果我将上面的代码更改为以下内容,我将得到预期的输出:(这是这次的整个文件...)
package com.hellomvp.client;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.hellomvp.events.ResponseEvent;
public class RequestManager {
private EventBus eventBus;
private String cachedResponse;
private HelloServiceAsync service = GWT.create(HelloService.class);
public RequestManager(EventBus eventBus)
{
this.eventBus = eventBus;
}
public void callServer(final Object source)
{
if(cachedResponse != null)
{
System.err.println("Getting Response from Cache for: "+ source.getClass().getName());
service.doNothing(new AsyncCallback<Void>(){
@Override
public void onFailure(Throwable caught) {
System.err.println("RPC Call Failed.");
}
@Override
public void onSuccess(Void result) {
eventBus.fireEventFromSource(new ResponseEvent(cachedResponse),source);
}
});
}
else
{
System.err.println("Getting Response from Server for: "+ source.getClass().getName());
service.callServer(new AsyncCallback<String>(){
@Override
public void onFailure(Throwable caught) {
System.err.println("RPC Call Failed.");
}
@Override
public void onSuccess(String result) {
cachedResponse = result;
eventBus.fireEventFromSource(new ResponseEvent(cachedResponse),source);
}
});
}
}
}
所以指出,唯一的变化是我创建了一个新的RPC 调用不执行任何操作,而是在其回调中发送事件,并使用缓存的数据,从而使应用程序按预期工作。
所以问题是:
我做错了什么?我不明白为什么“eventBus.fireEvent(...)”需要在 RPC 回调中才能正常工作。我认为这是一个线程问题,但我在谷歌上搜索任何有帮助的东西都是徒劳的。
我有一个完整的 Eclipse 项目展示了我遇到的这个问题,它可以在以下位置找到: Eclipse 问题项目示例
编辑:请注意,使用 eventBus.fireEventFromSource(...)
仅用于调试目的,因为在我的实际 GWT 应用程序中,我有多个已注册的事件处理程序。那么如何正确使用EventBus?
Background Story:
I am developing a GWT application, using the standard MVP design pattern, and also using RPC to get data from my custom data handling servlet (does a lot behind the scenes). Anyway, my goal is to create a very simple custom caching mechanism, that stores the data returned from the RPC callback in a static cache POJO. (The callback also sends a custom event using the SimpleEventBus to all registered handlers.) Then when I request the data again, I'll check the cache before doing the RPC server call again. (And also send a custom event using the EventBus).
The Problem:
When I send the event from the RPC callback, everything works fine. The problem is when I send the event outside the RPC callback when I just send the cached object. For some reason this event doesn't make it to my registered handler. Here is some code:
public void callServer(final Object source)
{
if(cachedResponse != null)
{
System.err.println("Getting Response from Cache for: "+ source.getClass().getName());
//Does this actually fire the event?
eventBus.fireEventFromSource(new ResponseEvent(cachedResponse),source);
}
else
{
System.err.println("Getting Response from Server for: "+ source.getClass().getName());
service.callServer(new AsyncCallback<String>(){
@Override
public void onFailure(Throwable caught) {
System.err.println("RPC Call Failed.");
}
@Override
public void onSuccess(String result) {
cachedResponse = result;
eventBus.fireEventFromSource(new ResponseEvent(cachedResponse),source);
}
});
}
}
Now I have two Activities, HelloActivity and GoodbyeActivity (taken from: GWT MVP code)
They also print out messages when the handler is called. Anyway, this is the output I get from the logs: (Not correct)
Getting Response from Cache for: com.hellomvp.client.activity.HelloActivity
Response in GoodbyeActivity from: com.hellomvp.client.activity.HelloActivity
Getting Response from Cache for: com.hellomvp.client.activity.GoodbyeActivity
Response in HelloActivity from: com.hellomvp.client.activity.GoodbyeActivity
What I expect to get is this:
Getting Response from Cache for: com.hellomvp.client.activity.HelloActivity
Response in HelloActivity from: com.hellomvp.client.activity.HelloActivity
Getting Response from Cache for: com.hellomvp.client.activity.GoodbyeActivity
Response in GoodbyeActivity from: com.hellomvp.client.activity.GoodbyeActivity
And I will get this expected output if I change the above code to the following: (This is the entire file this time...)
package com.hellomvp.client;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.hellomvp.events.ResponseEvent;
public class RequestManager {
private EventBus eventBus;
private String cachedResponse;
private HelloServiceAsync service = GWT.create(HelloService.class);
public RequestManager(EventBus eventBus)
{
this.eventBus = eventBus;
}
public void callServer(final Object source)
{
if(cachedResponse != null)
{
System.err.println("Getting Response from Cache for: "+ source.getClass().getName());
service.doNothing(new AsyncCallback<Void>(){
@Override
public void onFailure(Throwable caught) {
System.err.println("RPC Call Failed.");
}
@Override
public void onSuccess(Void result) {
eventBus.fireEventFromSource(new ResponseEvent(cachedResponse),source);
}
});
}
else
{
System.err.println("Getting Response from Server for: "+ source.getClass().getName());
service.callServer(new AsyncCallback<String>(){
@Override
public void onFailure(Throwable caught) {
System.err.println("RPC Call Failed.");
}
@Override
public void onSuccess(String result) {
cachedResponse = result;
eventBus.fireEventFromSource(new ResponseEvent(cachedResponse),source);
}
});
}
}
}
So the point it out, the only change is that I created a new RPC call that does nothing, and send the event in its callback, with the cached data instead, and it causes the application to work as expected.
So the Question:
What am I doing wrong? I don't understand why 'eventBus.fireEvent(...)' Needs to be in an RPC Callback to work properly. I'm thinking this is a threading issue, but I have searched Google in vain for anything that would help.
I have an entire Eclipse project that showcases this issue that I'm having, it can be found at: Eclipse Problem Project Example
Edit: Please note that using eventBus.fireEventFromSource(...)
is only being used for debugging purposes, since in my actual GWT Application I have more than one registered Handler for the events. So how do you use EventBus properly?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
如果我正确理解您的问题,您期望对
SimpleEventBus#fireEventFromSource
的调用仅路由到source
对象。情况并非如此 - 事件总线将始终向所有注册的处理程序触发事件。一般来说,使用 EventBus 的目标是将事件源与其处理程序分离 - 基于事件源的功能与此目标背道而驰。要获得您想要的行为,请将
AsyncCallback
传递到缓存 RPC 客户端,而不是尝试以非预期的方式使用EventBus
概念。这样做的另一个好处是,当 RPC 调用失败时,可以向有问题的Activity
发出警报:并且在
Activity
中:If I understand your problem correctly you are expecting calls to
SimpleEventBus#fireEventFromSource
to be routed only to thesource
object. This is not the case - the event bus will always fire events to all registered handlers. In general the goal of using anEventBus
is to decouple the sources of events from their handlers - basing functionality on thesource
of an event runs counter to this goal.To get the behavior you want pass an
AsyncCallback
to your caching RPC client instead of trying to use theEventBus
concept in a way other than intended. This has the added benefit of alerting theActivity
in question when the RPC call fails:And in the
Activity
: