1

I am trying to write a simple example that uses the switchOnNext operator. I want to generate an infinite stream of infinite streams. EAch individual stream will generate from 1 to infinity.

Using switchOnNext I would expect that each observable will emit it's first n elements, and then the next one, and so on.

To generate an observable that generates values from 1 to infinty I have implemented the static rangeInf function. The main method contains the logic that is supposed to print the values.

When running the program however only the first stream is subscribed to and only its values are printed to the console. For sanity's sake I took the interval observable (built-in and also infinite), but there the behaviour is as expected.

What am I missing here?

At first I figured it would be because interval is on its own seperate thread. But I tried adding .observeOn(Schedulers.computation()) in the rangeInf method, but that doesn't seem to fix the problem either.

Output with interval

> Task :Main.main()
Next observable
id 144: value 1
id 144: value 1
id 144: value 1
id 144: value 1
id 144: value 1
id 144: value 1
id 144: value 1
id 144: value 1
id 144: value 1
Next observable
id 115: value 1
id 115: value 1
id 115: value 1
id 115: value 1
...

Output with Observable.generate

> Task :Main.main()
Next observable
id 173: value 0
id 173: value 1
id 173: value 2
id 173: value 3
id 173: value 4
id 173: value 5
...

Source

import io.reactivex.rxjava3.annotations.NonNull;
import io.reactivex.rxjava3.core.*;
import io.reactivex.rxjava3.functions.BiConsumer;
import io.reactivex.rxjava3.functions.BiFunction;
import io.reactivex.rxjava3.functions.Consumer;
import io.reactivex.rxjava3.functions.Supplier;
import io.reactivex.rxjava3.schedulers.Schedulers;

import java.util.Random;
import java.util.concurrent.TimeUnit;

public class Main {
    static Random r = new Random();
    public static void main(String[] args) throws InterruptedException {
        Observable<Observable<String>> inf =
                Observable.interval(0, 10, TimeUnit.SECONDS)
                        .map(x -> {
                            int id = r.nextInt(1000);
                            return Main.rangeInf().map(v -> String.format("%d: %d", id, v));
                        })
                        .doOnNext(i -> System.out.println("Next observable"));

        Observable.switchOnNext(inf)
                .subscribe(System.out::println);

        while(true) {
            Thread.sleep(10000);
        }
    }

    public static Observable<Integer> inf() {
        Observable<Integer> inf=  Observable.interval(1, TimeUnit.SECONDS)
                .map(x -> (int) Math.random() * 3000 + 1);

        return inf;

    }
    public static Observable<Integer> rangeInf() {
        // Initial state.
        Supplier<Integer> s = () -> 0;
        // Generator.
        BiFunction<Integer, Emitter<Integer>, Integer> nxt = (i, e) -> {
            e.onNext(i);
            delay(); // delay random amount of time.
            return i + 1;
        };
        return Observable.generate(s, nxt);
    }

    public static void delay() {
        int random = (int) (Math.random() * 1 + 1);
        try {
            Thread.sleep(random * 1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
Christophe De Troyer
  • 2,852
  • 3
  • 30
  • 47

0 Answers0