Android 即使在调用onBackpressureBlock()之后,也会丢失BackPressureException
我试图周期性地(每150ms)发出事件,即使上游可观测对象会更快地发送事件 但是我得到了Android 即使在调用onBackpressureBlock()之后,也会丢失BackPressureException,android,reactive-programming,rx-java,Android,Reactive Programming,Rx Java,我试图周期性地(每150ms)发出事件,即使上游可观测对象会更快地发送事件 但是我得到了missingbackpressureeexception,即使我调用了onBackpressureBlock() 代码: PS:Log.fatalError(err)只是我对Android.util.Log.e(…) 编辑 经过多次尝试和错误,这对我来说是一个无法解决的问题zipWith(Observable.interval…似乎是罪魁祸首,可能是框架缺陷。删除这些行(以及我的周期性发射功能)我的代码可以
missingbackpressureeexception
,即使我调用了onBackpressureBlock()
代码:
PS:Log.fatalError(err)
只是我对Android.util.Log.e(…)
编辑
经过多次尝试和错误,这对我来说是一个无法解决的问题<代码>zipWith(Observable.interval…
似乎是罪魁祸首,可能是框架缺陷。删除这些行(以及我的周期性发射功能)我的代码可以正常工作。
我使用的主题可能从不同的线程调用了onNext
,然后我对其执行Obeservable运算符。我认为(但我不确定)问题在于您的背压配置在zip
运算符之后
zip
操作员需要缓冲一个observatable
的项目,以将其与另一个observatable
进行压缩。这就是应该引发异常的缓冲区。(见附件)
为了解决您的问题,我认为您应该尝试在zip
操作符中使用的一个(或每个)Observable
上添加背压配置
例如:
obs.zipWith(Observable.interval(150, TimeUnit.MILLISECONDS).onBackPressureDrop());
obs.onBackPressureBlock().zipWith(Observable.interval(150, TimeUnit.MILLISECONDS));
以上来自@dwursteisen和@zsxwing的答案是正确的 间隔操作符是基于时间发出的操作符,因此是“热”的,不支持背压。因此,它将继续发出并填充zip的内部有界缓冲区,这将导致MissingBackpressureException 在处理“热”源(例如基于时间或用户事件的源)时,必须选择如何处理溢出的策略 在这种情况下,您需要将该策略置于
interval
操作符上
下面的代码显示了正在发生的事情以及处理这些事情的选项:
import java.util.concurrent.TimeUnit;
import rx.Observable;
public class ZipInterval {
public static void main(String... args) {
Observable<Long> slowHotSource = Observable.interval(1, TimeUnit.SECONDS);
/** This one is fast and hot so will cause a MissingBackpressureException.
*
* This is because a "hot" source based on time does not obey backpressure
* and keeps emitting regardless of what the downstream asks for.
*
* Examples of "hot" and "cold" and approaches to both can be found at:
* https://speakerdeck.com/benjchristensen/reactive-programming-with-rx-at-qconsf-2014?slide=90 and
* https://github.com/ReactiveX/RxJava/wiki/Backpressure
* */
// Observable<Long> fastHotSource = Observable.interval(1, TimeUnit.MILLISECONDS);
/**
* The following version of 'fastHotSource' composes a simple flow control strategy.
*/
Observable<Long> fastHotSource = Observable.interval(1, TimeUnit.MILLISECONDS).onBackpressureDrop();
Observable<String> zipped = Observable.zip(slowHotSource, fastHotSource, (s, f) -> {
return s + " " + f;
});
// subscribe to the output
System.out.println("---- zip output");
zipped.take(10).toBlocking().forEach(System.out::println);
/**
* The outcome of the above is probably not what is expected though.
*
* This is because zip will buffer the output and then `fastHotSource` will drop until
* the zip buffer asks for more.
*
* For temporal or "hot" sources like this, using `withLatestFrom` or `combineLatest`
* is often more appropriate than `zip`.
*/
Observable<String> latest = slowHotSource.withLatestFrom(fastHotSource, (s, f) -> {
return s + " " + f;
});
// subscribe to the output
System.out.println("---- latest output");
latest.take(10).toBlocking().forEach(System.out::println);
}
}
尝试使用
combinelatetest
,因为combinelastest不会等待新值调用onNext,当新值到达函数时,它会使用最新值您是否同时尝试了这两种方法?根据你的描述,很难知道哪一个太快了。
obs.zipWith(Observable.interval(150, TimeUnit.MILLISECONDS).onBackPressureDrop());
obs.onBackPressureBlock().zipWith(Observable.interval(150, TimeUnit.MILLISECONDS));
import java.util.concurrent.TimeUnit;
import rx.Observable;
public class ZipInterval {
public static void main(String... args) {
Observable<Long> slowHotSource = Observable.interval(1, TimeUnit.SECONDS);
/** This one is fast and hot so will cause a MissingBackpressureException.
*
* This is because a "hot" source based on time does not obey backpressure
* and keeps emitting regardless of what the downstream asks for.
*
* Examples of "hot" and "cold" and approaches to both can be found at:
* https://speakerdeck.com/benjchristensen/reactive-programming-with-rx-at-qconsf-2014?slide=90 and
* https://github.com/ReactiveX/RxJava/wiki/Backpressure
* */
// Observable<Long> fastHotSource = Observable.interval(1, TimeUnit.MILLISECONDS);
/**
* The following version of 'fastHotSource' composes a simple flow control strategy.
*/
Observable<Long> fastHotSource = Observable.interval(1, TimeUnit.MILLISECONDS).onBackpressureDrop();
Observable<String> zipped = Observable.zip(slowHotSource, fastHotSource, (s, f) -> {
return s + " " + f;
});
// subscribe to the output
System.out.println("---- zip output");
zipped.take(10).toBlocking().forEach(System.out::println);
/**
* The outcome of the above is probably not what is expected though.
*
* This is because zip will buffer the output and then `fastHotSource` will drop until
* the zip buffer asks for more.
*
* For temporal or "hot" sources like this, using `withLatestFrom` or `combineLatest`
* is often more appropriate than `zip`.
*/
Observable<String> latest = slowHotSource.withLatestFrom(fastHotSource, (s, f) -> {
return s + " " + f;
});
// subscribe to the output
System.out.println("---- latest output");
latest.take(10).toBlocking().forEach(System.out::println);
}
}
---- zip output
0 0
1 1
2 2
3 3
4 4
5 5
6 6
7 7
8 8
9 9
---- latest output
0 1002
1 2002
2 3000
3 4001
4 5003
5 6001
6 7000
7 8002
8 9005
9 10000