简体   繁体   中英

How to process each item differently in a Observable stream(RxJava)

Let me put an example: Given the stream of numbers from 1 to 10, process even and odd numbers differently. Process odd numbers in a different thread and apply this transformation to them (2 * i). Process even numbers in the main thread and apply this transformation to them (2 * i - 1). The subscriber is below:

finalObservable.subscribe(new Action1<Integer>() {
   @Override
   public void call(Integer t) {
      System.out.println(Thread.currentThread() + " " + t);
   }});

The output should be

Thread-1 2
main 3
Thread-1 6
main 7
Thread-1 10
main 11
Thread-1 14
main 15
Thread-1 18
main 19

How to do this using RxJava-Observables operators?

The most elegant way to handle this problem is to use share() operator of the Observable . In a huuuuge simplification it lets you split your observable into multiple ones. So in your case, an observable representing a stream of numbers, can be split into two observables. One for odd numbers and one for even numbers.

Assuming allNumbers (in your example finalObservable ) represents the <1, 10> numbers stream:

final Observable<Integer> allNumbers =
        Observable.from(new Integer[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10})
                .share();
Observable<Integer> oddNumbers = allNumbers.filter(new Func1<Integer, Boolean>() {
    @Override
    public Boolean call(Integer integer) {
        return integer % 2 != 0;
    }
});
Observable<Integer> evenNumbers = allNumbers.filter(new Func1<Integer, Boolean>() {
    @Override
    public Boolean call(Integer integer) {
        return integer % 2 == 0;
    }
});

final Action1<Integer> printingAction = new Action1<Integer>() {
    @Override
    public void call(Integer t) {
        System.out.println(Thread.currentThread() + " " + t);
    }
};

evenNumbers.subscribeOn(Schedulers.computation()).subscribe(printingAction);
oddNumbers.subscribeOn(AndroidSchedulers.mainThread()).subscribe(printingAction);

And simplified with Retrolambda:

final Observable<Integer> allNumbers =
        Observable.from(new Integer[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10})
                .share();
Observable<Integer> oddNumbers = allNumbers.filter(integer -> integer % 2 != 0);
Observable<Integer> evenNumbers = allNumbers.filter(integer -> integer % 2 == 0);

final Action1<Integer> printingAction = 
         t -> System.out.println(Thread.currentThread() + " " + t);

evenNumbers.subscribeOn(Schedulers.computation()).subscribe(printingAction);
oddNumbers.subscribeOn(AndroidSchedulers.mainThread()).subscribe(printingAction);

You didn't specify exactly what needs to be processed in which thread, so you might need to correct subscribeOn arguments and maybe add observeOn operators. Depending on your needs.

The general idea will be something like this (using flatMap ):

Observable.from(new Integer[]{1, 2, 3, 4, 5})
          .flatMap(number -> {
              if (number % 2 == 0) {
                  return Observable.just(2 * number - 1);
              } else {
                  return Observable.fromCallable(() -> 2 * number)
                                   .subscribeOn(Schedulers.io());
              }
          })
          .subscribe(new Action1<Integer>() {
              @Override
              public void call(Integer integer) {
                  System.out.println(Thread.currentThread() + " " + integer);
              }
          });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM