在RxJava2中将Observable转换为具有背压的Flowable

时间:2017-10-23 08:52:35

标签: java android kotlin rx-java rx-java2

我正在观察由NetworkResource生成的行,并将其包裹在Observable.create中。这是代码,缺少try / catch和取消以简化:

fun linesOf(resource: NetworkResource): Observable<String> =
        Observable.create { emitter ->
            while (!emitter.isDisposed) {
                val line = resource.readLine()
                Log.i(TAG, "Emitting: $line")
                emitter.onNext(line)
            }
        }

问题在于,稍后我想使用Flowable将其转换为observable.toFlowable(LATEST)以添加背压,以防我的消费者无法跟上,但取决于我是如何做到的,消费者在第128项之后停止接收物品。

A)这样一切正常:

val resource = ...
linesOf(resource)
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .toFlowable(BackpressureStrategy.LATEST)
    .subscribe { Log.i(TAG, "Consuming: $it") }

B)这里消费者在128件商品后卡住(但继续发货):

val resource = ...
linesOf(resource)
    .toFlowable(BackpressureStrategy.LATEST)
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe { Log.i(TAG, "Consuming: $it") } // <-- stops after 128

在选项 A)中,所有内容都可以正常运行,我可以看到Emitting: ...日志与Consuming: ...日志并排。

在选项 B)中,我可以看到Emitting: ...日志消息愉快地发出新行,但我在第128项后停止看到Consuming: ...日志消息,即使发出继续进行。

问题:有人可以帮我理解为什么会这样吗?

1 个答案:

答案 0 :(得分:4)

首先,您使用了错误的类型和错误的运算符。使用Flowable无需转换。使用Flowable.generate可以获得背压:

Flowable.generate(emitter -> {
    String line = resource.readLine();
    if (line == null) {
        emitter.onComplete();
    } else {
        emitter.onNext(line);
    }
});

其次,您的版本挂起的原因是由subscribeOn导致的同一个池死锁。来自下游的请求安排在您急切的排放回路后面,并且无法生效,在默认的128个元素处停止排放。使用Flowable.subscribeOn(scheduler, false)来避免这种情况。