我想用RxJava实现EventBus,我需要粘性事件。我知道我可以使用BehaviorSubject但它只缓存最后发出的项目,而我想缓存所有类型(类名称)不同的事件。还有另一种选择 - ReplaySubject,但它有一个开销 - 它包含所有发射的元素。 有没有办法创建某种ReplaySubject,它只能按类型元素保存?
答案 0 :(得分:1)
我不相信有任何干净的解决方案。但是,您可能能够完成这项工作。
BehaviorSubject<>
。使用ConcurrentMap
将每个传入的事件分派到正确的Subject
。这是一些可能澄清上述内容的代码。未经测试。
// 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