INTRO TO RXJAVA
& RXANDROID
Egor Andreevici
WHAT?
HOW?
WHY?
& A DEMO
WHAT IS RXJAVA?
“RXJAVA IS A JAVA VM IMPLEMENTATION OF
REACTIVEX (REACTIVE EXTENSIONS): A
LIBRARY FOR COMPOSING ASYNCHRONOUS
AND EVENT-BASED PROGRAMS BY USING
OBSERVABLE SEQUENCES.”
RxJava Wiki
WHAT IS RXJAVA?
WHAT IS RXJAVA?
OBSERVABLES (AND MARBLE DIAGRAMS)
WHAT IS RXJAVA?
PROGRAM STRUCTURE
subscription = Observable
.create(…)
.transform(…)
.subscribe(...);
HOW RXJAVA?
HOW RXJAVA?
THE HIGH LEVEL PLAN
▸ Create an Observable
▸ Manipulate data using operators
▸ Subscribe and consume
▸ Profit!
HOW RXJAVA?
CREATING OBSERVABLES: CREATE()
Observable.create(subscriber -> {
try {
for (int value = 1; value <= 3; value++) {
subscriber.onNext(value);
}
subscriber.onCompleted();
} catch (Throwable t) {
subscriber.onError(t);
}
});
HOW RXJAVA?
THE OBSERVER INTERFACE
public interface Observer<T> {
void onCompleted();
void onError(Throwable e);
void onNext(T t);
}
HOW RXJAVA?
THE NOTIFICATIONS CONTRACT
▸ Zero or more onNext() notifications
▸ Either onCompleted() or onError(), not both!
▸ Nothing more!
▸ May never terminate
▸ May never call onCompleted()
▸ All notifications must be issued serially
HOW RXJAVA?
CREATING OBSERVABLES: JUST()
Observable.just(1);
Observable.just(1, 2);
Observable.just(1, 2, 3);
. . .
Observable.just(1, … , 9);
HOW RXJAVA?
CREATING OBSERVABLES: FROM()
Observable.from(Arrays.asList(1, 2, 3));
Observable.from(new Integer[]{1, 2, 3});
HOW RXJAVA?
CREATING OBSERVABLES: MISC
Observable.empty();
Observable.error(t);
Observable.never();
HOW RXJAVA?
Observable.create(subscriber -> {
try {
for (int i = 0; i < 10000; i++) {
T value = longRunningNetworkRequest();
subscriber.onNext(value);
}
subscriber.onCompleted();
} catch (Throwable t) {
subscriber.onError(t);
}
});
CAVEATS: HANDLING UNSUBSCRIBING
HOW RXJAVA?
SUBSCRIPTION INTERFACE
public interface Subscription {
void unsubscribe();
boolean isUnsubscribed();
}
HOW RXJAVA?
CAVEATS: HANDLING UNSUBSCRIBING
Observable.create(subscriber -> {
try {
for (int i = 0; i < 10000; i++) {
if (subscriber.isUnsubscribed()) {
return;
}
T value = longRunningNetworkRequest();
subscriber.onNext(value);
}
subscriber.onCompleted();
} catch (Throwable t) {
subscriber.onError(t);
}
});
HOW RXJAVA?
OPERATORS
▸ Transformational
▸ map()
▸ flatMap()
▸ concatMap()
▸ Filtering
▸ filter()
▸ take()
▸ skip()
▸ Combining
▸ merge()
▸ zip()
▸ combineLatest()
AND MANY MORE…
HOW RXJAVA?
OPERATORS: FILTER()
HOW RXJAVA?
OPERATORS: MAP()
HOW RXJAVA?
OPERATORS: FLATMAP()
HOW RXJAVA?
OPERATORS: ZIP()
HOW RXJAVA?
SUBSCRIBING TO OBSERVABLES
.subscribe(
value -> renderValue(value),
error -> renderError(error),
() -> Log.d(LOGTAG, "Done!"));
HOW RXJAVA?
MULTITHREADING: OPERATORS
Observable<T> observeOn(Scheduler scheduler) {}
Observable<T> subscribeOn(Scheduler scheduler) {}
HOW RXJAVA?
MULTITHREADING: SCHEDULERS
Schedulers.io()
Schedulers.computation()
Schedulers.newThread()
Schedulers.from(Executor)
HOW RXJAVA?
TESTING: BLOCKING OBSERVABLES
@Test
public void testingWithBlockingObservable() {
Observable<Integer> intObservable =
Observable.just(1, 2, 3);
BlockingObservable<Integer> blocking =
intObservable.toBlocking();
assertThat(blocking.first()).isEqualTo(1);
assertThat(blocking.last()).isEqualTo(3);
blocking.getIterator();
blocking.toIterable();
}
HOW RXJAVA?
TESTING: TESTSUBSCRIBER
@Test
public void testingWithTestSubscriber() {
Observable<Integer> intObservable =
Observable.just(1, 2, 3);
TestSubscriber<Integer> testSubscriber =
TestSubscriber.create();
intObservable.subscribe(testSubscriber);
testSubscriber.assertValues(1, 2, 3);
testSubscriber.assertNoErrors();
testSubscriber.assertCompleted();
}
HOW RXJAVA?
DEBUGGING: SIDE EFFECTS
Observable.just(1, 2, 3)
.doOnNext(next -> append("Before filter: " + next))
.filter(value -> value % 2 == 0)
.doOnNext(next -> append("After filter: " + next))
.subscribe(...);
RXJAVA ON ANDROID
RXJAVA ON ANDROID
RXANDROID
▸ Super tiny
▸ AndroidSchedulers.mainThread()
▸ HandlerScheduler.from(Handler)
RXJAVA ON ANDROID
RXBINDING
▸ RxJava binding APIs for Android's UI widgets
▸ RxView.clicks(…), RxView.enabled(…) etc.
▸ RxTextView.textChanges(…)
RXJAVA ON ANDROID
RXLIFECYCLE
▸ Lifecycle handling APIs for Android apps using RxJava
▸ .compose(RxLifecycle.bindActivity(lifecycle))
▸ RxActivity, RxFragment
▸ .compose(bindToLifecycle())
RXJAVA ON ANDROID
RETROFIT: THE UGLY
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
GithubApiClient client = createGithubApiClient();
try {
List<Repo> repos = client.getRepos().execute().body();
// render repos
} catch (IOException e) {
// handle
}
}
RXJAVA ON ANDROID
RETROFIT: THE BAD
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
GithubApiClient client = createGithubApiClient();
client.getRepos().enqueue(new Callback<List<Repo>>() {
@Override
public void onResponse(Call<List<Repo>> call,
Response<List<Repo>> response) {
// render repos
}
@Override
public void onFailure(Call<List<Repo>> call,
Throwable t) {
// handle
}
});
}
RXJAVA ON ANDROID
RETROFIT: THE GOOD
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
GithubApiClient client = createGithubApiClient();
subscription = client.getRepos()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
repos -> renderRepos(repos),
error -> handleError(error));
}
WHY RXJAVA?
WHY RXJAVA?
WHY RXJAVA?
▸ Set of powerful operators
▸ Easy threading
▸ Explicit error handling
▸ Testable
▸ Lots of perks specific to Android
DEMO TIME!
THANK YOU!
Egor Andreevici
blog.egorand.me · @EgorAnd · +EgorAndreevich

Intro to RxJava/RxAndroid - GDG Munich Android