RxJava映射并在单个映射完成后立即发出

时间:2016-06-13 17:40:37

标签: android multithreading rx-java reactive-programming

我希望将对象映射/转换为后台线程中的另一个对象,并在单个对话完成后立即将其置于主线程上。

Observable.just(1,2,3,4,5)
            .map(new Func1<Integer, String>() {
                @Override
                public String call(Integer integer) {
                    Log.d(TAG, "mapping number " + integer);
                    return String.valueOf(integer) + " mapped on: " + Thread.currentThread().getName();
                }
            })
            .subscribeOn(Schedulers.newThread())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Observer<String>() {
                @Override
                public void onCompleted() {
                    Log.d(TAG, "onCompleted on: " + Thread.currentThread().getName());
                }

                @Override
                public void onError(Throwable e) {
                }

                @Override
                public void onNext(String integer) {
                    Log.d(TAG, integer + " received on: "+ Thread.currentThread().getName());
                }
            });

结果是:

D: mapping number 1
D: mapping number 2
D: mapping number 3
D: mapping number 4
D: mapping number 5
D: 1 mapped on: RxNewThreadScheduler-1 received on: main
D: 2 mapped on: RxNewThreadScheduler-1 received on: main
D: 3 mapped on: RxNewThreadScheduler-1 received on: main
D: 4 mapped on: RxNewThreadScheduler-1 received on: main
D: 5 mapped on: RxNewThreadScheduler-1 received on: main
D: onCompleted on: main

但转换可能需要一段时间,我希望转换完成后立即收到。

D: mapping number 1
D: 1 mapped on: RxNewThreadScheduler-1 received on: main
D: mapping number 2
D: 2 mapped on: RxNewThreadScheduler-1 received on: main
D: mapping number 3
D: 3 mapped on: RxNewThreadScheduler-1 received on: main
D: mapping number 4
D: 4 mapped on: RxNewThreadScheduler-1 received on: main
D: mapping number 5
D: 5 mapped on: RxNewThreadScheduler-1 received on: main
D: onCompleted on: main

2 个答案:

答案 0 :(得分:3)

无需设置全局缓冲区大小,只需使用observeOn(Scheduler, int)重载,您可以将预取值指定为1.如果已处理前一个值,则只会询问下一个值。

答案 1 :(得分:0)

这是由于RxJava对您正在使用的链中的运算符施加背压。 ObserveOn等下游运营商通过数据块从上游请求数据,而不是通过单个项目来提高效率。如果将缓冲区大小设置为1,这将有效地实现您期望的效率成本:

-Drx.ring-buffer.size=1

具体而言,那对于有昂贵的往返电话的上游来说非常糟糕。

修改

您可以使用带有BehaviorSubject的zip来排序下行和上行流的排序:

BehaviorSubject<Void> signal = BehaviorSubject.create();
signal.onNext(null); // <- pair up the signal with the first item immediately
Observable.just(1,2,3,4,5)
        .zipWith(signal, (item,v)->item) //only emit a next item when there is a "receipt acknowledgement" from the down stream
        .observeOn(Schedulers.newThread()) //<- needed to avoid fetching subsequent items in UI thread
        .map(new Func1<Integer, String>() {
            @Override
            public String call(Integer integer) {
                Log.d(TAG, "mapping number " + integer);
                return String.valueOf(integer) + " mapped on: " + Thread.currentThread().getName();
            }
        })
        .subscribeOn(Schedulers.newThread())
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(new Observer<String>() {
            @Override
            public void onCompleted() {
                Log.d(TAG, "onCompleted on: " + Thread.currentThread().getName());
            }

            @Override
            public void onError(Throwable e) {
            }

            @Override
            public void onNext(String integer) {
                Log.d(TAG, integer + " received on: "+ Thread.currentThread().getName());
                signal.onNext(null);  //<- acknowledge receipt - allow emitting next item from upstream
            }
        });