EventBus为一个帖子调用两个不同的处理程序

时间:2017-03-12 00:33:37

标签: android greenrobot-eventbus-3.0

我遇到了EventBus 3.0.0的问题,我发布了这样的单个事件:

Call<List<SessionSpec>> call = httpService.getSessionSpecs();
call.enqueue(new Callback<List<SessionSpec>>() {

   @Override
   public void onResponse(Call<List<SessionSpec>> call, Response<List<SessionSpec>> response)  {
       if (response.isSuccessful())  {
           List<SessionSpec> specs = response.body();
           EventBus.getDefault().post((List<SessionSpec>)specs);
       }
       else Log.e(TAG, "sendSessionSpecs(): request NOT successful");
   }

   @Override
   public void onFailure(Call<List<SessionSpec>> call, Throwable t)  {
      Log.e(TAG, "sendSessionsSpecs(): failed");
   }
});

我在同一个片段中有两个订阅者,每个订阅者都有不同的签名,但是他们都是从一个帖子中调用的:

@Subscribe
public void onSessionSpec(List<SessionSpec> specs) {
    Log.d(TAG, "onSessionSpec(): entered");
    Log.d(TAG, "    : number of session specs: " + specs.size());
}

第二个订户定义为:

@Subscribe
public void onOverlayType(List<OverlayType> types) {
    Log.d(TAG, "onOverlayType(): entered");
    Log.d(TAG, "    : number of overlay types: " + types.size());
}

这两个回调都在一个片段中,当帖子完成后我就确认帖子只被调用一次。发布单个SessionSpec事件时,事件类型为List&gt;的EventBus将调度onSessionSpec和onOverlayType回调。所以onOverlayType回调在其回调参数中收到错误的类型。 OverlayType类是一个简单的POJO类,有2个成员,一个int“sid”和一个String“name”。 SessionSpec类更复杂;它确实有一个成员字符串“name”但除此之外,这两个类之间没有其他共同点。我已经确认在SessionSpec类中没有类似“OverlayType”的内容。

接口定义如下:

public interface VcapHttpInterface {

    @GET("overlay/types")
    Call<List<OverlayType>> getOverlayTypes();

    @GET("session/list")
    Call<List<SessionSpec>> getSessionSpecs();

    @GET("session/{id}")
    Call<Session> getSession(@Path("id") int sid);

}

getSession事件发布/回调没有问题。

我花了一整天的时间试图弄清楚出了什么问题,所以我现在一点都不知道。有人知道我的代码可能有什么问题吗?

谢谢, -Andres

编辑:EventBus如何知道为特定响应调用哪个处理程序?我读过的一些帖子说EventBus不使用处理程序签名,但是如何知道如何将响应映射到正确的订阅处理程序例程呢?有没有办法明确定义给定事件的处理程序回调?

2 个答案:

答案 0 :(得分:2)

EventBus检查您要发布的对象的类,并在其参数中调用期望该类的方法。在您的情况下,您要发布一个List的对象。在两个侦听器中,您都期望类型为List的对象。您放入OverlayTypeSessionSpec的通用名称并不重要,eventbus会同时调用这两种语法。为了使其工作,您必须将模型定义为事件。

public class OverlayTypeEvent {

    public List<OverlayType> types;

    public OverlayTypeEvent(List<OverlayType> types) {
        this.types = types;
    }
}

public class SessionSpecEvent {

    public List<SessionSpec> types;

    public SessionSpecEvent(List<SessionSpec> types) {
        this.types = types;
    }
}

听他们说seperatley。然后发布具有特定类型的事件。

@Subscribe
public void onSessionSpec(OverlayTypeEvent event) {
    List<OverlayType> overlayTypes = event.overlayType;
}

答案 1 :(得分:0)

如果您不想每次发送列表数据时都将新类作为容器创建,则可以Pair作为简单容器,它具有两个通用字段(第一个第二)以包含变量。

您可以使用 first 作为键来检查类的类型, second 包含实际数据。

List<SessionSpec> specs = response.body();
EventBus.getDefault().post(new Pair<>(SessionSpec.class.getSimpleName(), specs));

接收数据:

@Subscribe
public void onSessionSpec(Pair<String, List<SessionSpec>> specContainer){
    if (SessionSpec.class.getSimpleName().equals(specContainer.first)) {
        List<SessionSpec> sessionSpecs = specContainer.second;
    }
}

@Subscribe
public void onOverlayType(Pair<String, List<OverlayType>> overlayContainer) {
    if (OverlayType.class.getSimpleName().equals(overlayContainer.first)) {
        List<OverlayType> overlayTypes = overlayContainer.second;
    }
}
此解决方案的

优点:减少创建不必要的类。
缺点 onSessionSpec onOverlayType 都被调用。