Google Web Toolkit (GWT) EventBus запускает / обрабатывает события - PullRequest
2 голосов
/ 09 июня 2011

История вопроса:
Я занимаюсь разработкой приложения GWT, используя стандартный шаблон проектирования MVP, а также использую RPC для получения данных из моего собственного сервлета обработки данных (многое делает за кулисами). В любом случае, моя цель - создать очень простой пользовательский механизм кэширования, который хранит данные, возвращаемые из обратного вызова 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, чтобы работать должным образом. Я думаю, что это проблема с многопоточностью, но я тщетно искал в Google все, что могло бы помочь.

У меня есть целый проект Eclipse, который демонстрирует эту проблему, которую я имею, ее можно найти по адресу: Пример проекта проблемы Eclipse



Изменить: Обратите внимание, что использование eventBus.fireEventFromSource(...) используется только для целей отладки, поскольку в моем реальном приложении GWT у меня есть несколько зарегистрированных обработчиков для событий. Итак, как правильно использовать EventBus ?

1 Ответ

1 голос
/ 09 июня 2011

Если я правильно понимаю вашу проблему, вы ожидаете, что вызовы на SimpleEventBus#fireEventFromSource будут направлены только на объект source.Это не так - шина событий всегда будет запускать события для всех зарегистрированных обработчиков.В общем, цель использования EventBus состоит в том, чтобы отделить источники событий от их обработчиков - основание функциональности на source события идет вразрез с этой целью.

Чтобы получить поведение, которое вы хотите передатьAsyncCallback для вашего кэширующего RPC-клиента вместо того, чтобы пытаться использовать концепцию EventBus иным способом, чем предполагалось.Это дает дополнительное преимущество, сообщая об Activity, о котором идет речь, при сбое вызова RPC:

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);
  }
});
...