1
votes

I often find myself creating streams which depend on some condition provided by a Single<Boolean>. Consider this example:

@Test
public void test() {
    Observable.range(0, 10)
            .flatMapSingle(this::shouldDoStuff)
            .flatMapCompletable(shouldDoStuff -> shouldDoStuff ? doStuff() : Completable.complete())
            .test();
}

private Single<Boolean> shouldDoStuff(int number) {
    return Single.just(number % 2 == 0);
}

private Completable doStuff() {
    return Completable.fromAction(() -> System.out.println("Did stuff"));
}

I find the flatMapSingle(...).flatMapCompletable(...) part to be unnecessary verbose.

Maybe there are operators available that could simplify this, e.g.:

Observable.range(0, 10)
        .flatMapSingle(this::shouldDoStuff)
        .flatMapCompletableIfTrue(doStuff())
        .test();

Or a static constructor that wraps the two lines, e.g.:

Observable.range(0, 10)
        .flatMapCompletable(number -> Completable.ifTrue(shouldDoStuff(number), doStuff()))
        .test();

Please let me know how you would implement this if this kind of condition check would be part of many of your streams.

1

1 Answers

1
votes

You could use the filter operator on the result of shouldDoStuff

 Observable.range(0, 10)
            .flatMapSingle(this::shouldDoStuff)
            .filter(shouldDo -> shouldDo)  // this will emit to the downstream only if shouldDo = true
            .flatMapCompletable(__ -> doStuff())
            .test();

Or try writing a wrapper to make the code more readable, (by moving your same logic to wrapper )

  class CompletableIfTrue {
    public static CompletableSource when(Single<Boolean> shouldDoStuff, Completable doStuff) {
        return shouldDoStuff.flatMapCompletable(shouldDo -> shouldDo ? doStuff : Completable.complete());
    }

And

Observable.range(0, 10)
     .flatMapCompletable(number -> CompletableIfTrue.when(shouldDoStuff(number), doStuff()))
     .test();