Google Web Toolkit (GWT) EventBus 事件触发/处理

Posted

技术标签:

【中文标题】Google Web Toolkit (GWT) EventBus 事件触发/处理【英文标题】:Google Web Toolkit (GWT) EventBus event firing/handling 【发布时间】:2011-06-08 22:41:38 【问题描述】:

背景故事: 我正在开发一个 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 code) 它们还会在调用处理程序时打印出消息。无论如何,这是我从日志中得到的输出:(不正确)

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

我期望得到的是:

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 Problem Project Example

编辑:请注意,使用 eventBus.fireEventFromSource(...) 仅用于调试目的,因为在我的实际 GWT 应用程序中,我有多个注册的事件处理程序。那么如何正确使用EventBus呢?

【问题讨论】:

【参考方案1】:

如果我正确理解您的问题,您预计对 SimpleEventBus#fireEventFromSource 的调用将仅路由到 source 对象。情况并非如此 - 事件总线将始终向所有已注册的处理程序触发事件。一般来说,使用EventBus 的目标是将事件源与其处理程序分离——基于事件的source 的功能与此目标背道而驰。

要获得您想要的行为,请将 AsyncCallback 传递给缓存 RPC 客户端,而不是尝试以非预期方式使用 EventBus 概念。这具有在 RPC 调用失败时提醒有问题的 Activity 的额外好处:

public class RequestManager 
  private String cachedResponse = null;
  private HelloServiceAsync service = GWT.create(HelloService.class);

  public void callServer(final AsyncCallback<String> callback) 
    if (cachedResponse != null) 
      callback.onSuccess(cachedResponse);
     else 
      service.callServer(new AsyncCallback<String>()
        @Override
        public void onFailure(Throwable caught) 
          callback.onFailure(caught);
        

        @Override
        public void onSuccess(String result) 
          cachedResponse = result;
          callback.onSuccess(cachedResponse);
        
      );
    
  

而在Activity

clientFactory.getRequestManager().callServer(new AsyncCallback<String>() 
  @Override
  public void onFailure(Throwable caught) 
    // Handle failure.
  

  @Override
  public void onSuccess(String result) 
    helloView.showResponse(result);
  
);

【讨论】:

我理解使用 EventBus 将事件源与其处理程序分离的概念,并且我只是将 fireEventfromSource 用于调试目的,以找出事件从哪里开始以及它们要去哪里。我需要使用 EventBus 向所有处理程序触发事件,在我的实际应用程序中(这仅用于演示)有多个,此解决方案仅适用于一个处理程序。

以上是关于Google Web Toolkit (GWT) EventBus 事件触发/处理的主要内容,如果未能解决你的问题,请参考以下文章

Google Web Toolkit (GWT) EventBus 事件触发/处理

在 Google Web Toolkit (GWT) 中实现页眉、页脚和菜单栏

Google Web Toolkit (GWT) rpc 到 Google App Engine (GAE) 上的 Python 服务器

带有 MySQL 的 Google Web Toolkit (GWT) Web 应用程序在 Eclipse 中运行良好,但在 openSUSE 服务器上无法运行

在Google Web Toolkit中使用自定义字体

运行mvn包时出现Google web toolkit错误