Observables, Operators & the Reactive Contract
The Observable Contract
RxJava is the JVM implementation of ReactiveX — composing async/event-based programs via observable streams. An Observable emits any number of onNext(item) calls, followed by exactly one terminal onComplete or onError, never both. It models a sequence over time, from a single value to an infinite stream.
Cold vs. Hot Observables
By default, Observables are cold — nothing happens until subscribe() is called, and each subscriber typically gets its own fresh execution of the sequence. A hot Observable emits regardless of subscribers (like a live broadcast); a late subscriber can miss earlier emissions.
Composing with Operators
searchQueries
.debounce(300, TimeUnit.MILLISECONDS)
.filter(q -> q.length() > 2)
.flatMap(q -> api.search(q))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(results -> render(results));Operators compose a declarative pipeline: debounce waits for a quiet period (avoiding a request per keystroke), filter excludes short queries, flatMap maps each query to its own async search Observable and flattens the results. map, by contrast, is a plain synchronous 1-to-1 transform — flatMap is for when each item triggers its own async operation returning another Observable.
Schedulers: subscribeOn vs. observeOn
subscribeOn controls which thread the source's work runs on, regardless of where it's placed in the chain. observeOn controls which thread everything downstream of it receives emissions on, and can appear multiple times to switch threads partway through — a common source of confusion for newcomers to the library.
Keep your own version of these notes — editable, searchable, and organised by your stack.
Start free