Intro to RxJava/RxAndroid - GDG Munich Android
-
Upload
egor-andreevici -
Category
Software
-
view
1.031 -
download
0
Transcript of Intro to RxJava/RxAndroid - GDG Munich Android
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
@Testpublic 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
@Testpublic 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
@Overridepublic 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@Overridepublic void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
GithubApiClient client = createGithubApiClient(); client.getRepos().enqueue(new Callback<List<Repo>>() {
@Overridepublic 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
@Overridepublic 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!