ReplaySubject具有不同的元素

时间:2017-09-04 09:30:00

标签: rx-java2 behaviorsubject

我想用RxJava实现EventBus,我需要粘性事件。我知道我可以使用BehaviorSubject但它只缓存最后发出的项目,而我想缓存所有类型(类名称)不同的事件。还有另一种选择 - ReplaySubject,但它有一个开销 - 它包含所有发射的元素。 有没有办法创建某种ReplaySubject,它只能按类型元素保存?

2 个答案:

答案 0 :(得分:1)

我不相信有任何干净的解决方案。但是,您可能能够完成这项工作。

  1. 为每种事件类型创建BehaviorSubject<>。使用ConcurrentMap将每个传入的事件分派到正确的Subject
  2. 按事件到达顺序维护这些科目的清单。
  3. 当收到新订阅时,将创建一个可观察对象,即所有主题的合并,第一个已经收到事件的主题列表,然后是那些没有任何顺序的主题。
  4. 这是一些可能澄清上述内容的代码。未经测试。

    // The subscription operation will perform a merge of the two lists
    Map<EventType, BehaviorSubject<Event>> map = new ConcurrentHashMap<>();
    List<BehaviorSubject<Event>> listOfUnseenEvents = new ArrayList<>();
    List<BehaviorSubject<Event>> listOfSeenEvents = new ArrayList<>();
    // ...
    listOfUnseenEvents = map.values().asList();
    
    public Observable<Event> busSub() {
      List<BehaviorSubject<Event>> allEvents = new ArrayList<>();
      synchronized ( map ) {
        allEvents.addAll( listOfSeenEvents );
        allEvents.addAll( listOfUnseenEvents );
      }
      return Observable.merge( allEvents );
    }
    
    // receive an event and dispatch it
    eventSource
      .subscribe( event -> processEvent( event ) );
    
    public void processEvent( Event event ) {
        BehaviorSubject<Event> eSubject = map.get( event.getEventType() );
        synchronized ( map ) {
          if ( containsEventType( listOfSeenEvents, event.getEventType() ) ) {
            removeEventType( listOfSeenEvents, event.getEventType() );
          } else {
            removeEventType( listOfUnseenEvents, event.getEventType() );
          }
          listOfSeenEvents.add( eSubject );
        }
        eSubject.onNext( event );
    }
    

    请注意,此代码利用merge()将按顺序订阅每个给定的可观察量的事实。 RxJava文档中无法保证这一点。

    如果事先不知道所有事件类型,那么这将无法正常工作。

答案 1 :(得分:1)

仅通过一个流就无法成功解决此问题。
因此,我按事件类型只有一个流,并且只公开合并的流。

open class Event(val name: String)
class Event1(name: String) : Event(name)
class Event2(name: String) : Event(name)

val event1Subject = BehaviorSubject.create<Event1>()
val event2Subject = BehaviorSubject.create<Event2>()

event1Subject.onNext(Event1("event1 a"))
event1Subject.onNext(Event1("event1 b"))
event2Subject.onNext(Event2("event2 a"))
event2Subject.onNext(Event2("event2 b"))

Observable.merge(event1Subject, event2Subject)
        .subscribe { println(it.name) }

控制台输出:

event1 b
event2 b