我在RxJava2上比较新,而且我得到了一些奇怪的行为,所以很可能我错误地使用了这个工具。
这是一个相当大的项目,但我已将下面的代码段分开作为最低可重现代码:
Observable
.interval(333, TimeUnit.MILLISECONDS)
.flatMap(new Function<Long, ObservableSource<Integer>>() {
private Subject<Integer> s = PublishSubject.create();
private int val = 0;
@Override public ObservableSource<Integer> apply(Long aLong) throws Exception {
val++;
s.onNext(val);
return s;
}
})
.subscribe(new Consumer<Integer>() {
@Override public void accept(Integer integer) throws Exception {
Log.w("value: %s", integer);
}
});
此代码使用.interval
模拟来自我的rx流的事件,flatMap
接收这些事件&#34;进行一些处理&#34;并使用Subject
将结果推送到流中。
流是一个持续的过程,将有几个事件。
这个最低限度的代码很愚蠢,因为我只推动apply
回调,但在实际案例中,有几个可能发生推送的时刻和收到的事件数量期间apply
与通过主题发送的金额不同。
我期望看到的代码是:
value: 2 // 1 got skipped because onNext is called before there's a subscriber.
value: 3
value: 4
value: 5
value: 6 ... etc
我实际得到的是:
value: 2
value: 3
value: 3 // 3 twice
value: 4
value: 4
value: 4 // 4 repeated 3 times
value: 5
value: 5
value: 5
value: 5 // 5 repeated 4 times
value: 6
value: 6
value: 6
value: 6
value: 6 // 6 repeated 5 times
... etc
我还试图获得Observable<Integer> o = s.share();
并将其返回,或直接返回s.share();
并获得相同的结果。
我有点理解为什么会这样。 ObservableSource
再次n再次订阅n,因此每次循环都会有更多事件。
问题:
我如何实现预期的行为?
(如果我的预期行为不明确,请在评论中提出更多意见)
答案 0 :(得分:1)
您的PublishSubject
多次订阅 ,每个项目间隔一次()。
修改:您需要每次都传递一个新的PublishSubject
(如果您想要保留第一个/最后一个发射,请切换到BehaviorSubject
);将其传递给长时间运行的进程,并确保在长时间运行的进程完成时正确调用其onComplete
。
答案 1 :(得分:1)
修改强>
在最近的评论之后,我可以想出这种解决方案:
class MyBluetoothClient {
private PublishSubject<BTLEEvent> statusPublishSubject = PublishSubject.create()
public Observable<BTLEEvent> getEventObservable() {
return statusPublishSubject
}
private void publishEvent(BTLEEvent event) {
statusPublishSubject.onNext(event)
}
public void doStuff1() {
// do something that returns:
publishEvent(BTLEEvent.someEvent1)
}
public void doStuff2() {
// do something else that eventually yields
publishEvent(BTLEEvent.someEvent2)
}
}
你以这种方式使用它:
MyBluetoothClient client = MyBluetoothClient()
client
.getEventObservable()
.subscribe( /* */ )
///
client.doStuff1()
///
client.doStuff2
原始回答
这会吗?
Observable
.interval(333, TimeUnit.MILLISECONDS)
.flatMap(new Function<Long, ObservableSource<Integer>>() {
private int val = 0;
@Override public ObservableSource<Integer> apply(Long aLong) throws Exception {
val++;
return Observable.just(val);
}
})
.subscribe(new Consumer<Integer>() {
@Override public void accept(Integer integer) throws Exception {
Log.w("value: %s", integer);
}
});
答案 2 :(得分:0)
所以这就是我想出的答案。我将@Tassos的答案标记为正确,因为他指出了我正确的道路。
首先我需要一个CachedSubject
(一个缓存项目的主题,而没有观察者并在观察者连接后立即发送它们),这对于确保{{1}内的排放是必要的。真的通过了。该课主要包装apply
。
PublishSubject
然后我将这个类与class CachedSubject<T> extends Subject<T> {
private PublishSubject<T> publishSubject = PublishSubject.create();
private Queue<T> cache = new ConcurrentLinkedQueue<>();
@Override public boolean hasObservers() {
return publishSubject.hasObservers();
}
@Override public boolean hasThrowable() {
return publishSubject.hasThrowable();
}
@Override public boolean hasComplete() {
return publishSubject.hasComplete();
}
@Override public Throwable getThrowable() {
return publishSubject.getThrowable();
}
@Override protected void subscribeActual(Observer<? super T> observer) {
while (cache.size() > 0) {
observer.onNext(cache.remove());
}
publishSubject.subscribeActual(observer);
}
@Override public void onSubscribe(Disposable d) {
publishSubject.onSubscribe(d);
}
@Override public void onNext(T t) {
if (hasObservers()) {
publishSubject.onNext(t);
} else {
cache.add(t);
}
}
@Override public void onError(Throwable e) {
publishSubject.onError(e);
}
@Override public void onComplete() {
publishSubject.onComplete();
}
}
:
switchMap
这实际上允许我在Observable
.interval(1000, TimeUnit.MILLISECONDS)
.switchMap(new Function<Long, ObservableSource<Integer>>() {
private Subject<Integer> s = new CachedSubject<>();
private int val = 0;
@Override public ObservableSource<Integer> apply(Long aLong) throws Exception {
val++;
s.onNext(val);
return s;
}
})
.subscribe(new Consumer<Integer>() {
@Override public void accept(Integer integer) throws Exception {
Log.w("value: %s", integer);
}
});
方法上接收任意数量的事件,只有1 apply<T t>
订阅它,从中接收所有事件。