16

I have a chain of operators on an RxJava observable. I'd like to be able to apply one of two operators depending on a boolean value without "breaking the chain".

I'm relatively new to Rx(Java) and I feel like there's probably a more idiomatic and readable way of doing this than my current approach of introducing a temporary variable.

Here's a concrete example, buffering items from an observable if a batch size field is non-null, otherwise emitting a single batch of unbounded size with toList():

Observable<Item> source = Observable.from(newItems);
Observable<List<Item>> batchedSource = batchSize == null ?
                source.toList() :
                source.buffer(batchSize);
return batchedSource.flatMap(...).map(...)

Is something like this possible? (pseudo-lambdas because Java):

Observable.from(newItems)
    .applyIf(batchSize == null,
             { o.toList() },
             { o.buffer(batchSize) })
    .flatMap(...).map(...)
user1405990
  • 806
  • 1
  • 8
  • 19

2 Answers2

21

You can use compose(Func1) to stay in-sequence but do custom behavior

source
.compose(o -> condition ? o.map(v -> v + 1) : o.map(v -> v * v))
.filter(...)
.subscribe(...)
akarnokd
  • 69,132
  • 14
  • 157
  • 192
  • 2
    Perfect! Thanks very much. `compose()` doesn't currently show up in the official operator docs but a quick search surfaced a nice blog post literally called "Don't break the chain": http://blog.danlew.net/2015/03/02/dont-break-the-chain/ – user1405990 Mar 17 '16 at 20:09
  • What if the condition is inside of the item itself? example: wallpapers.map { it.bitmap != null { download & set } else { just set} } – frankelot Dec 01 '17 at 05:21
  • 1
    Use `flatMap` or `concatMap`. – akarnokd Dec 01 '17 at 07:59
1

You can also use filter operator with defaultIfEmpty if you wish to emit single value or switchIfEmpty if you wish to emit multiple values using another Observable.

val item = Observable.just("ABC")

item.filter { s -> s.startsWith("Z") }
    .defaultIfEmpty("None")
    .subscribe { println(it) }
Thracian
  • 43,021
  • 16
  • 133
  • 222