RxJava:特定类型的BehaviorSubject

时间:2017-02-09 16:41:47

标签: rx-java rx-android

我正在尝试实现某种RxBus,它允许发布特定类型的事件并根据对象类来监听它们。我正在使用BehaviorSubject来支持粘性事件(即使在订阅之前也可以发布)。并且应该为每种类型保留粘性事件。这是代码:

private final Subject<BaseEvent, BaseEvent> bus = new SerializedSubject<>(BehaviorSubject.create());

public <E extends BaseEvent> void post(E event) {
    bus.onNext(event);
}

public <E extends BaseEvent> Observable<E> observe(Class<E> eventClass) {
    return bus.asObservable().ofType(eventClass);
}

它适用于一种类型的事件。但是当有更多不同的事件,并且最后发布的事件与我订阅的事件类型不同时,它会被ofType()过滤,因为BehaviorSubject只保留最后一个不依赖于类型的事件。

我在想两个解决方案:

  1. 要为每种类型创建主题地图,但子类型存在问题。
  2. 使用ReplaySubject并使用ofType()和distinct()过滤事件。但是我无法找到区分订阅之前和之后发出的事件的方法。
  3. 您如何看待,有没有办法让这些解决方案发挥作用,或者我可能缺少某些东西,并且有更好的方法来实现它?

1 个答案:

答案 0 :(得分:1)

首先,您不需要主题,而是Relay

我建议你第三个解决方案:编写你自己的Relay(或Subject)实现,它将记住所有不同的事件。您不需要从头开始重写Relay或Subject,您可以依赖现有的实现(这里是PublishRelay):

import com.jakewharton.rxrelay2.PublishRelay;
import com.jakewharton.rxrelay2.Relay;

import java.util.HashMap;
import java.util.Map;

import io.reactivex.Observer;

public class RxBus extends Relay<Object> {

    private PublishRelay<Object> concreteRelay = PublishRelay.create();
    private Map<Class, Object> stickyEvents = new HashMap<>();

     public <T> T getSticky(Class<T> type) {
         return (T)stickyEvents.get(type);
     }

    @Override
    public void accept(Object value) {
        stickyEvents.put(value.getClass(), value);
        concreteRelay.accept(value);
    }

    @Override
    public boolean hasObservers() {
        return concreteRelay.hasObservers();
    }

    @Override
    protected void subscribeActual(Observer<? super Object> observer) {
        concreteRelay.subscribeActual(observer);
    }
}