Reactive Programming
with RxJava
By: Farzad Tabashir
Video Lecture: https://www.youtube.com/watch?v=BH9Rb-FeDE0&list=PLT2xIm2X7W7gq_fD5HMWca1rWQQFeETK-
Outline
- Introduction
- RxJava: Essential Concepts
- RxJava: Advanced Concepts
- RxJava for Android Developers
Introduction
Declarative / Imperative
Declarative / Imperative
Declarative programming
what the program must accomplish
rather than describe how to accomplish it as a sequence of the programming language primitives
Declarative / Imperative
Declarative Programming |
Impretavie Programming Language (Java) |
Assembly |
Binary Codes |
Hardware |
Reactive Programming
Reactive Programming
wikipedia: data flows and propagation of change
simple: pushing data instead of pulling it
Reactive Programming
Reactive Extensions
implement reactive programming paradigm over sequence of data
Rx History
-
Rx.NET 2009
-
RxJS 2010
-
RxJava 1.x 2014 by Netflix
Java, Scala, C#, C++, Clojure, JavaScript, Python, Groovy, JRuby, and others
Who use ReactiveX?
RxJava
is a JVM library which
implements reactive programming
in a declarative approach
with a functional style
What reactive-functional programming is solving?
Short answer:
- concurrency and parallelism
-
More colloquially, it is solving callback hell
- addressing reactive and asynchronous use cases in an imperative way
RxJava
-
There are different approaches to being “reactive,”
- and RxJava is but one of them
-
RxJava is a
- concrete implementation of reactive programming principles
- influenced by functional and data-flow programming.
-
If your program is like most though,
-
you need to combine events (asynchronous responses from functions/network calls)
-
have conditional logic interacting between them
-
and must handle failure scenarios and resource cleanup on any and all of them
-
This is where the reactive-imperative approach begins to dramatically increase in complexity and reactive-functional programming begins to shine
When You Need Reactive Programming
RxJava: Essentials
Observable
-
Central to RxJava is the Observable type
- a stream of data/events
- It is intended for push (reactive) but can also be used for pull (interactive).
- It is lazy rather than eager.
- It can be used asynchronously or synchronously.
- It can represent 0, 1, many, or infinite values or events over time.
-
“asynchronous/push ‘dual' to the synchronous/pull Iterable.”
-
By “dual,” we mean the Observable provides all the functionality of an Iterable except in the reverse flow of data: it is push instead of pull
-
Observable/Observer pair
interface Observable<T> {
Subscription subscribe(Observer s)
}
interface Observer<T> {
void onNext(T t)
void onError(Throwable t)
void onCompleted()
}
Iterable
for (Story story : stories) {
Log.i(TAG, story.getTitle());
}
//This is equivalent to the following:
for (Iterator<Story> iterator = stories.iterator(); iterator.hasNext();) {
Story story = iterator.next();
Log.i(TAG, story.getTitle());
}
Iterable
- Synchronous data stream
- Pull
Observable
- Asynchronous data stream
- Push
Pull (Iterable) | Push (Observable) |
---|---|
T next() | onNext(T) |
throws Exception | onError(Throwable) |
returns | onCompleted() |
Iterable
Observable
// Iterable<String> as Stream<String>
// that contains 75 strings
getDataFromLocalMemorySynchronously()
.skip(10)
.limit(5)
.map(s -> s + "_transformed")
.forEach(System.out::println)
// Observable<String>
// that emits 75 strings
getDataFromNetworkAsynchronously()
.skip(10)
.take(5)
.map(s -> s + "_transformed")
.subscribe(System.out::println)
Operators
- work on observable
- return observable
- can be chained
Map
transform the items emitted by an Observable by applying a function to each item
Filter
emit only those items from an Observable that pass a predicate test
Operators
Most of these operators are synchronous, meaning that they perform their computation synchronously inside the onNext() as the events pass by.
Concurrency
A single Observable stream is always serialized, but each Observable stream can operate independently of one another, and thus concurrently and/or in parallel.
Schedulers (Threading)
- Threading in RxJava defined by Schedulers
- Parts of a data flow can run on different threads
- Use schedulers instead of Threads
Schedulers
- computation()
- io()
- mainThread()
- newThread()
- from(Executor)
- from(Looper)
Schedulers
- operators have their default scheduler
- check java doc
Schedulers
-
subscribeOn(Scheduler)
-
observeOn(Scheduler)
Schedulers
-
subscribeOn(Scheduler)
-
multiple calls useless
-
only the first call works
-
for all operators
-
Schedulers
-
observeOn(Scheduler)
-
can be called multiple times
-
changes scheduler downstream
-
RxJava: Advanced
Observable Types
-
Observable<T>
- Emits 0 or n items and terminates with an success or an error event
-
Single<T>
- Emits either a single item or an error event. The reactive version of a method call
-
Maybe<T>
- Succeeds with an item, or no item, or errors. The reactive version of an Optional.
-
Completable
- Either completes with an success or with an error event. It never emits items. The reactive version of a Runnable.
Operators
Creating
Just
create an Observable that emits a particular item
From
convert various other objects and data types into Observables
Range
create an Observable that emits a particular range of sequential integers
Timer
create an Observable that emits a particular item after a given delay
Interval
create an Observable that emits a sequence of integers spaced by a given time interval
Create
create an Observable from scratch by means of a function
Defer
do not create the Observable until the observer subscribes, and create a fresh Observable for each observer
Empty/Never/Throw
no items / not terminate / terminates with an error
Operators
Combining
Concat
emit the emissions from two or more Observables without interleaving them
Merge
combine multiple Observables into one by merging their emissions
Amb
given two or more source Observables, emit all of the items from only the first of these Observables
Zip
combine the emissions of multiple Observables together via a specified function and emit single items for each combination based on the results of this function
combineLatest
When Streams Are Not Synchronized with One Another
WithLatestFrom
All slow events appearing before the first fast event are silently dropped because there is nothing with which to combine them.
Operators
Transforming
Map
transform the items emitted by an Observable by applying a function to each item
Buffer
periodically gather items emitted by an Observable into bundles and emit these bundles rather than emitting the items one at a time
Scan
apply a function to each item emitted by an Observable, sequentially, and emit each successive value
FlatMap
transform the items emitted by an Observable into Observables, then flatten the emissions from those into a single Observable
GroupBy
divide an Observable into a set of Observables that each emit a different subset of items from the original Observable
Window
periodically subdivide items from an Observable into Observable windows and emit these windows rather than emitting the items one at a time
Operators
Filtering
First
emit only the first item (or the first item that meets some condition) emitted by an Observable
Last
emit only the last item (or the last item that meets some condition) emitted by an Observable
Skip
suppress the first n items emitted by an Observable
Take
emit only the first n items emitted by an Observable
Distinct
suppress duplicate items emitted by an Observable
Sample
emit the most recent items emitted by an Observable within periodic time intervals
Debounce
(throtleWithTimeout)
only emit an item from an Observable if a particular timespan has passed without it emitting another item
Operators
Error Handling
Catch
recover from an onError notification by continuing the sequence without error
A Decision Tree of Observable Operators
Side Effect Methods
-
doOnNext()
-
doOnError()
-
doOnCompleted()
-
doOnSubscribe()
-
doOnUnsubscribe()
-
...
Async Composition
apiEndpoint.login()
.doOnNext(accessToken ->
storeCredentials(accessToken))
.flatMap(accessToken ->
serviceEndpoint.getUser())
.flatMap( user ->
serviceEndpoint.getUserContact(user.getId() ) )
RxJava in Android
why should i use?
Typical non-reactive app
Reactive app
RxAndroid
make writing reactive components in Android applications easy
More specifically, it provides a Scheduler that schedules on the main thread or any given Looper
RxAndroid
Observable.just("one", "two", "three", "four", "five")
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(/* an Observer */);
RxBinding
RxJava binding APIs for Android UI widgets
RxBinding
RxTextView.textChanges(searchTextView)
.filter( s -> s.length() > 2 )
.debounce(100, TimeUnit.MILLISECONDS)
.flatMap( s -> makeApiCall(s) )
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(/* attach observer */);
Retrofit
Retrofit
@POST("User/SignIn")
@FormUrlEncoded
Observable<LoginResponseModel> login(
@Field("username") String username,
@Field("password") String password,
);
SQLBrite & Room
Disposable and CompositeDisposable
CompositeDisposable compositeDisposable =
new CompositeDisposable();
compositeDisposable.add(
observable1.subscribe()
);
compositeDisposable.add(
observable2.subscribe()
);
// onPause, onStop
compositeDisposable.dispose();
Hot vs Cold Observable
Cold Observable
run their sequence when and if they are subscribed to
Hot Observable
- Emit values independent of individual subscriptions
- They have their own timeline and events occur whether someone is listening or not
Publish
Cold observables become hot with the publish() operator.
Back Pressure
asynchronous feedback channel
(also sometimes referred to as async-pull or reactive-pull)
Useful operators that avoid the need for backpressure
- throttle
- sample
- debounce
- buffers and windows
Back Pressure
class MySubscriber extends Subscriber<T> {
@Override
public void onStart() {
request(1);
}
@Override
public void onCompleted() {
...
}
@Override
public void onError(Throwable e) {
...
}
@Override
public void onNext(T n) {
...
request(1);
}
}
Real-World useful examples of using RxJava
- Background work & concurrency
- Instant/Auto searching text listeners
- Networking with Retrofit & RxJava
- Form validation
- Pseudo caching
- ...
We need
Asynchronous Programming
We need
reactive
Asynchronous Programming
We need
parallelisable
Asynchronous Programming
We need
composable
Asynchronous Programming
We need
readable
Asynchronous Programming
We need
RxJava !
Resourse
Reactive Programming with RxJava
By Farzad Tabashir
Reactive Programming with RxJava
You can see the video lecture (in persian) from here: https://www.youtube.com/watch?v=BH9Rb-FeDE0&list=PLT2xIm2X7W7gq_fD5HMWca1rWQQFeETK-
- 1,995