KEMBAR78
RxJava2 Slides | PPTX
- Reactive Extensions first introduced by Microsoft in 2009 for .NET
- Has been ported on most platforms and languages
History
Proved in production
“Unless you can model the entire system of your
app in a synchronous fashion, having a single
asynchronous source will ultimately break the
traditional imperative style of programming we’re
used to.”
What is RxJava?
RxJava is Reactive Extensions for the JVM - a library for
composing asynchronous and event-based programs using
Observable sequences for the Java VM
In other words we are pushing data instead of pulling it
without worrying about threads.
On top of that you are given an amazing toolbox of
functions to combine create and filter the streams
Advantages
● Simplifies the ability to chain async operations.
● Surfaces errors sooner.
● Easy threading
● Helps reduce the need for state variables that can introduce bugs.
Disadvantages
● The API surface area is large. consequently, the learning curve is steep
How to think in RxJava
Should I use RxJava 2 instead of 1?
YES!
- Mar 2018 - end of RxJava 1 support
- Better performance
- Lower memory consumption
- Can’t use null
- Backpressure (Flowable)
Iterable vs Observable, seems familiar?
Event Iterable Observable
retrieve data T next() onNext(T)
discover error throw Exception onError(Exception)
complete !hasNext() onCompleted()
transform fromIterable() toList()
Observables and Observers
The basic building blocks of reactive code are Observables
(Producer) and Observers (Consumer).
The Observable object is the one who does the job.
An Observer consumes the items emitted by the Observable.
An Observable calls Observer#onNext() for every item, followed
by either Observer#onComplete() or Observer#onError().
Observables and Friends
● Flowable: 0..N flows, supporting reactive streams and backpressure
● Observable: 0..N flows, no backpressure
● Single: a flow of exactly 1 item or am error
● Completable: a flow without items but only a completion or error signal
● Maybe: a flow with no items, exactly one item or an error
Creating Observable
Let's take the most basic example to understand how
this is structured.
Observable.just(“Hello!”)
Disposables
Disposables represents the link between your Observable and your Subscriber
val d: Disposable = Observable.just(“Hello!”).subscribe()
//Adding the disposable to CompositeDisposable
disposables.add(d)
//You can remove a disposable using delete method
disposables.delete(d)
//The container can be later reused
disposables.clear()
//The container cannot be reused
disposables.dispose()
Defining Observers
Let's take the most basic example to understand how
this is structured.
ApiService.doLogin(userID, userPassword).subscribe(new
Observer<String>() {
@Override
public void onNext(String s) { System.out.println("onNext: " + s); }
@Override
public void onCompleted() { System.out.println("done!"); }
@Override
public void onError(Throwable e) { }
});
public interface Observer<T> {
void onNext(T t);
void onCompleted();
void onError(Throwable e);
}
Consuming api request
val disposable = ApiService.doLogin(userID, userPassword)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({ loginResponse ->
hideLoading()
}, { error ->
showLog(error.message.toString())
} )
Operators
There is 248 operators we will focus on the common
- map()
- flatmap()
- filter()
- distinct()
- take()
- count()
Operators - Map
Transform the items emitted by an Observable by
applying a function to each item
Operators - Map - Example
Observable.just("Hello!")
.map(new Func1<String, String>() {
@Override
public String call(String s) {
return s + " Dan";
}
})
.subscribe(s -> showLog(s));
Observable.just("Hello!")
.map(s -> s + " Dan")
.subscribe{s -> showLog(s)}
@Deprecated...
Operators - Flatmap
- Transforms the items emitted by an Observable
into Observables, then flatten the emissions from
those into a single Observable (no order)
Operators - Flatmap - Example
Observable.just("Hello!")
.flatMap(new Func1<List<String>, Observable<String>>()
{
@Override
public Observable<String> call(List<String> urls) {
return Observable.from(urls);
}
})
.subscribe(url -> System.out.println(url));
Observable.just("Hello!")
.flatMap(urls -> Observable.from(urls))
.subscribe{s -> showLog(s)}
@Deprecated...
Flatmap vs Map
- Map returns an object of type T while FlatMap returns an Observable<T>.
- FlatMap - It basically merges an observable sequence of observable
sequences into a single observable sequence.
Operators - Filter
- Emits the same items it received, only if it passes
the boolean check (predicate)
Operators - Filter - Example
Observable.just("Hello!")
.flatMap(urls -> Observable.from(urls))
.flatMap(url -> getTitle(url))
.filter(title -> title != null)
.subscribe(url -> System.out.println(url));
Operators - Distinct
- The Distinct operator filters an Observable by only
allowing items through that have not already been
emitted.
Operators - Reduce - Example
Observable.just("Hello!")
.flatMap(urls -> Observable.from(urls))
.flatMap(url -> getTitle(url))
.distinct(title -> title.startsWith(“Hell”)
.subscribe(url -> System.out.println(url));
Operators - Take
- Emits only the first n items emitted by an Observable
Operators - Take - Example
Observable.just("Hello!")
.flatMap{urls -> Observable.from(urls)}
.flatMap{url -> getTitle(url)}
.filter{title -> title != null}
.take(5)
.subscribe{s -> showLog(s)}
Operators - Zip
- Emits when it has all the values to zip
Error handling
- onError() is called if an exception is thrown
at any time.
- The operators do not have to handle the
exception
public interface Observer<T> {
void onNext(T t);
void onCompleted();
void onError(Throwable e);
}
Error Operators
- onErrorResumeNext()
- onErrorReturn()
- onExceptionResumeNext()
- retry()
- retryWhen()
Multithread like a BOSS
Schedulers.io()
Unbounded thread pool
Schedulers.computation()
Bounded thread pool with size up to the number of processors
available.
Multithread Example
Observable.just("long", "longer", "longest")
.subscribeOn(Schedulers.computation())
.observeOn(AndroidSchedulers.mainThread())
.map(String::length)
.filter(length -> length == 6)
.subscribe(length -> System.out.println("item length " + length));
Multiple REST Calls
Observable<JsonObject> userObservable = repo
.create(User.class)
.getUser(loginName)
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread());
Observable<JsonArray> eventsObservable = repo
.create(Event.class)
.listEvents(loginName)
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread());
Retrofit repo = new Retrofit.Builder()
.baseUrl("https://api.github.com")
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
Let’s first setup two observables for the two network requests
below:
Zip magic
Observable<UserAndEvents> combined = Observable.zip(userObservable,
eventsObservable, new Func2<JsonObject, JsonArray, UserAndEvents>() {
@Override
public UserAndEvents call(JsonObject jsonObject, JsonArray jsonElements) {
return new UserAndEvents(jsonObject, jsonElements);
}
});
We use RxJava’s zip method to combine
our two Observables and wait for them to
complete before creating a new Observable.
Consume response
combined.subscribe(new Subscriber<UserAndEvents>() {
...
@Override
public void onNext(UserAndEvents o) {
// You can access the results of the
// two observabes via the POJO now
}
});
Finally let’s call the subscribe method on our new
combined Observable:
Login case
// force-disable the button
submitButton.setEnabled(false);
emailChangeObservable = RxTextView.textChangeEvents(email);
passwordChangeObservable = RxTextView.textChangeEvents(password);
Observable.combineLatest(emailChangeObservable, passwordChangeObservable,
(emailObservable, passwordObservable) -> {
boolean emailCheck = emailObservable.text().length() >= 3;
boolean passwordCheck = passwordObservable.text().length() >= 3;
return emailCheck && passwordCheck;
}).subscribe(aBoolean -> {
submitButton.setEnabled(aBoolean);
});
A common case that appears in almost every app that requires you to
have an account is the Sign In screen. I wanted to set up form validation
so that only when all fields are valid then a Sign In button would be
enabled.
Repository pattern example
public Observable<List<Repository>> getRepositories() {
Observable<List<Repository>> remote = getRemoteRepositories();
Observable<List<Repository>> local = getLocalRepositories();
return Observable.concat(local, remote);
}
What about Unit Testing?
What about Testings?
@Test
public void shouldLoadTwoUsers() throw Exception {
TestSubscriber<User> testSubscriber = new TestSubscriber<>();
databaseHelper.loadUser().subscribe(testSubscriber);
testSubscriber.assertNoErrors();
testSubscriber.assertReceivedOnNext(Arrays.asList(user1, user2))
}
TestSubscriber is a helper class provided by RxJava that we can use for
unit testing, to perform assertions, inspect received events, or wrap a
mocked Subscriber.
@Test
public void testValueCont() {
Observable.just("Hello","RxJava","Testing").subscribe(wordListTestSubscriber);
wordListTestSubscriber.assertValueCount(3);
}
Questions?
Questions :)

RxJava2 Slides

  • 1.
    - Reactive Extensionsfirst introduced by Microsoft in 2009 for .NET - Has been ported on most platforms and languages History
  • 2.
  • 3.
    “Unless you canmodel the entire system of your app in a synchronous fashion, having a single asynchronous source will ultimately break the traditional imperative style of programming we’re used to.”
  • 4.
    What is RxJava? RxJavais Reactive Extensions for the JVM - a library for composing asynchronous and event-based programs using Observable sequences for the Java VM In other words we are pushing data instead of pulling it without worrying about threads. On top of that you are given an amazing toolbox of functions to combine create and filter the streams
  • 5.
    Advantages ● Simplifies theability to chain async operations. ● Surfaces errors sooner. ● Easy threading ● Helps reduce the need for state variables that can introduce bugs.
  • 6.
    Disadvantages ● The APIsurface area is large. consequently, the learning curve is steep
  • 7.
    How to thinkin RxJava
  • 9.
    Should I useRxJava 2 instead of 1? YES! - Mar 2018 - end of RxJava 1 support - Better performance - Lower memory consumption - Can’t use null - Backpressure (Flowable)
  • 10.
    Iterable vs Observable,seems familiar? Event Iterable Observable retrieve data T next() onNext(T) discover error throw Exception onError(Exception) complete !hasNext() onCompleted() transform fromIterable() toList()
  • 11.
    Observables and Observers Thebasic building blocks of reactive code are Observables (Producer) and Observers (Consumer). The Observable object is the one who does the job. An Observer consumes the items emitted by the Observable. An Observable calls Observer#onNext() for every item, followed by either Observer#onComplete() or Observer#onError().
  • 12.
    Observables and Friends ●Flowable: 0..N flows, supporting reactive streams and backpressure ● Observable: 0..N flows, no backpressure ● Single: a flow of exactly 1 item or am error ● Completable: a flow without items but only a completion or error signal ● Maybe: a flow with no items, exactly one item or an error
  • 14.
    Creating Observable Let's takethe most basic example to understand how this is structured. Observable.just(“Hello!”)
  • 15.
    Disposables Disposables represents thelink between your Observable and your Subscriber val d: Disposable = Observable.just(“Hello!”).subscribe() //Adding the disposable to CompositeDisposable disposables.add(d) //You can remove a disposable using delete method disposables.delete(d) //The container can be later reused disposables.clear() //The container cannot be reused disposables.dispose()
  • 16.
    Defining Observers Let's takethe most basic example to understand how this is structured. ApiService.doLogin(userID, userPassword).subscribe(new Observer<String>() { @Override public void onNext(String s) { System.out.println("onNext: " + s); } @Override public void onCompleted() { System.out.println("done!"); } @Override public void onError(Throwable e) { } }); public interface Observer<T> { void onNext(T t); void onCompleted(); void onError(Throwable e); }
  • 17.
    Consuming api request valdisposable = ApiService.doLogin(userID, userPassword) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe({ loginResponse -> hideLoading() }, { error -> showLog(error.message.toString()) } )
  • 18.
    Operators There is 248operators we will focus on the common - map() - flatmap() - filter() - distinct() - take() - count()
  • 19.
    Operators - Map Transformthe items emitted by an Observable by applying a function to each item
  • 20.
    Operators - Map- Example Observable.just("Hello!") .map(new Func1<String, String>() { @Override public String call(String s) { return s + " Dan"; } }) .subscribe(s -> showLog(s)); Observable.just("Hello!") .map(s -> s + " Dan") .subscribe{s -> showLog(s)} @Deprecated...
  • 21.
    Operators - Flatmap -Transforms the items emitted by an Observable into Observables, then flatten the emissions from those into a single Observable (no order)
  • 22.
    Operators - Flatmap- Example Observable.just("Hello!") .flatMap(new Func1<List<String>, Observable<String>>() { @Override public Observable<String> call(List<String> urls) { return Observable.from(urls); } }) .subscribe(url -> System.out.println(url)); Observable.just("Hello!") .flatMap(urls -> Observable.from(urls)) .subscribe{s -> showLog(s)} @Deprecated...
  • 23.
    Flatmap vs Map -Map returns an object of type T while FlatMap returns an Observable<T>. - FlatMap - It basically merges an observable sequence of observable sequences into a single observable sequence.
  • 24.
    Operators - Filter -Emits the same items it received, only if it passes the boolean check (predicate)
  • 25.
    Operators - Filter- Example Observable.just("Hello!") .flatMap(urls -> Observable.from(urls)) .flatMap(url -> getTitle(url)) .filter(title -> title != null) .subscribe(url -> System.out.println(url));
  • 26.
    Operators - Distinct -The Distinct operator filters an Observable by only allowing items through that have not already been emitted.
  • 27.
    Operators - Reduce- Example Observable.just("Hello!") .flatMap(urls -> Observable.from(urls)) .flatMap(url -> getTitle(url)) .distinct(title -> title.startsWith(“Hell”) .subscribe(url -> System.out.println(url));
  • 28.
    Operators - Take -Emits only the first n items emitted by an Observable
  • 29.
    Operators - Take- Example Observable.just("Hello!") .flatMap{urls -> Observable.from(urls)} .flatMap{url -> getTitle(url)} .filter{title -> title != null} .take(5) .subscribe{s -> showLog(s)}
  • 30.
    Operators - Zip -Emits when it has all the values to zip
  • 31.
    Error handling - onError()is called if an exception is thrown at any time. - The operators do not have to handle the exception public interface Observer<T> { void onNext(T t); void onCompleted(); void onError(Throwable e); }
  • 32.
    Error Operators - onErrorResumeNext() -onErrorReturn() - onExceptionResumeNext() - retry() - retryWhen()
  • 33.
    Multithread like aBOSS Schedulers.io() Unbounded thread pool Schedulers.computation() Bounded thread pool with size up to the number of processors available.
  • 34.
    Multithread Example Observable.just("long", "longer","longest") .subscribeOn(Schedulers.computation()) .observeOn(AndroidSchedulers.mainThread()) .map(String::length) .filter(length -> length == 6) .subscribe(length -> System.out.println("item length " + length));
  • 35.
    Multiple REST Calls Observable<JsonObject>userObservable = repo .create(User.class) .getUser(loginName) .subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()); Observable<JsonArray> eventsObservable = repo .create(Event.class) .listEvents(loginName) .subscribeOn(Schedulers.newThread()) .observeOn(AndroidSchedulers.mainThread()); Retrofit repo = new Retrofit.Builder() .baseUrl("https://api.github.com") .addConverterFactory(GsonConverterFactory.create()) .addCallAdapterFactory(RxJavaCallAdapterFactory.create()) .build(); Let’s first setup two observables for the two network requests below:
  • 36.
    Zip magic Observable<UserAndEvents> combined= Observable.zip(userObservable, eventsObservable, new Func2<JsonObject, JsonArray, UserAndEvents>() { @Override public UserAndEvents call(JsonObject jsonObject, JsonArray jsonElements) { return new UserAndEvents(jsonObject, jsonElements); } }); We use RxJava’s zip method to combine our two Observables and wait for them to complete before creating a new Observable.
  • 37.
    Consume response combined.subscribe(new Subscriber<UserAndEvents>(){ ... @Override public void onNext(UserAndEvents o) { // You can access the results of the // two observabes via the POJO now } }); Finally let’s call the subscribe method on our new combined Observable:
  • 38.
    Login case // force-disablethe button submitButton.setEnabled(false); emailChangeObservable = RxTextView.textChangeEvents(email); passwordChangeObservable = RxTextView.textChangeEvents(password); Observable.combineLatest(emailChangeObservable, passwordChangeObservable, (emailObservable, passwordObservable) -> { boolean emailCheck = emailObservable.text().length() >= 3; boolean passwordCheck = passwordObservable.text().length() >= 3; return emailCheck && passwordCheck; }).subscribe(aBoolean -> { submitButton.setEnabled(aBoolean); }); A common case that appears in almost every app that requires you to have an account is the Sign In screen. I wanted to set up form validation so that only when all fields are valid then a Sign In button would be enabled.
  • 39.
    Repository pattern example publicObservable<List<Repository>> getRepositories() { Observable<List<Repository>> remote = getRemoteRepositories(); Observable<List<Repository>> local = getLocalRepositories(); return Observable.concat(local, remote); }
  • 40.
  • 41.
    What about Testings? @Test publicvoid shouldLoadTwoUsers() throw Exception { TestSubscriber<User> testSubscriber = new TestSubscriber<>(); databaseHelper.loadUser().subscribe(testSubscriber); testSubscriber.assertNoErrors(); testSubscriber.assertReceivedOnNext(Arrays.asList(user1, user2)) } TestSubscriber is a helper class provided by RxJava that we can use for unit testing, to perform assertions, inspect received events, or wrap a mocked Subscriber. @Test public void testValueCont() { Observable.just("Hello","RxJava","Testing").subscribe(wordListTestSubscriber); wordListTestSubscriber.assertValueCount(3); }
  • 44.