I would like for every emission from my Observable to have a delay occur AFTER its emission. i.e. For every item emitted from Observable.fromIterable(listOf(1,2,3))
I would like a variable/dynamic delay AFTERWARDS.
i.e. given a list of timers or delays [3, 5, 10]
, I would like for the following timeline to occur with my observable:
1 -> Wait 3 seconds -> 2 -> Wait 5 seconds -> 3 -> Wait 10 seconds
Please note that this is NOT the same as:
Wait 3 seconds -> 1 -> Wait 5 seconds -> 2 -> Wait 10 seconds -> 3
which can be easily achieved with .zip + .delay or Observable.Timer
Using zip()
is the right way to go. When you want the delay after the first value is emitted, then you can use startWith()
to add a zero delay for the first combination. The code might look like this:
Observable<Integer> values = Observable.fromArray(1,2,3,4,5);
Observable<Long> delays = Observable.fromArray(300L, 400L, 500L, 600L);
Observable<Integer> delayedValues = values.zipWith(
delays.startWith(0L),
new BiFunction<Integer, Long, Integer>() {
@Override
public Integer apply(Integer v, Long d) throws Exception {
Thread.sleep(d);
return v;
}
}
);
System.out.println("Begin subscribing");
long startTime = System.currentTimeMillis();
delayedValues.subscribe(v -> {
long currentTime = System.currentTimeMillis();
long diff = currentTime - startTime;
System.out.println("["+diff+"] "+v);
});
System.out.println("After subscribing");
This will generate the following output:
Begin subscribing
[35] 1
[336] 2
[736] 3
[1236] 4
[1836] 5
After subscribing
As you see, the first value is printed immediately, following by a 300ms delay for the next value until you reached the end.