Upgrade to Pro — share decks privately, control downloads, hide ads and more …

RxJava for Android - GDG DevFest LA 2016

Aaron He
December 04, 2016

RxJava for Android - GDG DevFest LA 2016

This is an introduction talk on RxJava for Android. I talked about why RxJava makes sense for me and some caveats.

Aaron He

December 04, 2016
Tweet

More Decks by Aaron He

Other Decks in Technology

Transcript

  1. aggregate all amb ambWith and asyncAction asyncFunc averageDouble averageFloat averageInteger

    averageLong buffer byLine cache cast chunkify collect combineLatest concat concatMap concatWith connect contains count countLong create debounce decode defaultIfEmpty defer deferFuture deferCancellableFuture delay dematerialize distinct distinctUntilChanged doOnCompleted doOnEach doOnError doOnNext doOnRequest doOnSubscribe doOnTerminate doOnUnsubscribe doWhile elementAt elementAtOrDefault empty encode error exists filter finallyDo first first firstOrDefault flatMap flatMapIterable forEach forEachFuture forIterable from fromAction fromCallable fromCancellableFuture fromFunc0 fromFuture fromRunnable generate generateAbsoluteTime getIterator groupBy groupByUntil groupJoin ifThen ignoreElements interval isEmpty join just last lastOrDefault latest limit map mapMany materialize max maxBy merge mergeDelayError mergeMap mergeMapIterable mergeWith min minBy mostRecent multicast never observeOn ofType onBackpressureBlock onBackpressureBuffer onBackpressureDrop onErrorFlatMap onErrorResumeNext onErrorReturn onExceptionResumeNext parallel parallelMerge pivot publish publishLast range reduce refCount repeat repeatWhen replay retry retrywhen runAsync sample scan sequenceEqual serialize share single singleOrDefault skip skipLast skipUntil
  2. Async Task public class Task extends AsyncTask<Void, Void, Void> {

    } @Override protected Void doInBackground(Void... params) { return null; }
  3. Async Task public class Task extends AsyncTask<Void, Void, Void> {

    } @Override protected Void doInBackground(Void... params) { return null; } @Override protected void onPostExecute(Void aVoid) { // Update UI. }
  4. Async Task public class Task extends AsyncTask<Void, Void, Void> {

    } @Override protected Void doInBackground(Void... params) { return null; } @Override protected void onPreExecute() { // Show progress bar. } @Override protected void onPostExecute(Void aVoid) { // Update UI. }
  5. Async Task public class Task extends AsyncTask<Void, Void, Void> {

    } @Override protected Void doInBackground(Void... params) { return null; } @Override protected void onProgressUpdate(Void... values) { // Update progress bar. } @Override protected void onPreExecute() { // Show progress bar. } @Override protected void onPostExecute(Void aVoid) { // Update UI. }
  6. Async Task public class Task extends AsyncTask<Void, Void, Void> {

    } @Override protected Void doInBackground(Void... params) { return null; } @Override protected void onProgressUpdate(Void... values) { // Update progress bar. } @Override protected void onCancelled(Void aVoid) { } @Override protected void onPreExecute() { // Show progress bar. } @Override protected void onPostExecute(Void aVoid) { // Update UI. }
  7. Async Task • Doesn’t work with Android lifecycle • Look

    at how many methods we might need to override
  8. Async Task • Doesn’t work with Android lifecycle • Look

    at how many methods we might need to override • Difficult to compose multiple tasks together
  9. Loader public class NetworkLoader extends AsyncTaskLoader<Void> { public NetworkLoader(Context context)

    { super(context); } @Override public Void loadInBackground() { return null; } }
  10. Loader public class NetworkLoader extends AsyncTaskLoader<Void> { public NetworkLoader(Context context)

    { super(context); } @Override public Void loadInBackground() { return null; } } getLoaderManager().initLoader(id, bundle, new LoaderManager.LoaderCallbacks<Void>() { @Override public Loader<Void> onCreateLoader(int id, Bundle args) { return new NetworkLoader(MainActivity.this); } @Override public void onLoadFinished(Loader<Void> loader, Void data) { } @Override public void onLoaderReset(Loader<Void> loader) { } });
  11. Services • It’s meant for long running background tasks •

    A little bit more code to talk back to UI
  12. Rx

  13. • Rx: Reactive Extension • Other implementations: RxKotlin, RxSwift, RxJs

    • Everything is a stream. • Easy to specify concurrency model. Rx
  14. Observer public interface Observer<T> { 
 } void onNext(T t);

    void onError(Throwable e); void onCompleted();
  15. Observable Observable .subscribe(
 
 
 
 
 
 ); new

    Observer<T>() {
 @Override public void onNext(T data) {
 }
 
 @Override public void onError(Throwable e) {
 }
 
 @Override public void onCompleted() {
 }
 }
  16. Observable creation Observable.just("Hello DevFest LA 2016"); Observable.fromCallable(new Callable<String>() {
 @Override

    public String call() throws Exception {
 return "Hello DevFest LA 2016";
 }
 }); Observable.from(list);
  17. Observable creation interface OnSubscribe<T> extends Action1<Subscriber<? super T>> {
 }

    abstract class Subscriber<T> implements Observer<T>, Subscription { }
  18. Observable creation interface OnSubscribe<T> extends Action1<Subscriber<? super T>> {
 }

    abstract class Subscriber<T> implements Observer<T>, Subscription { } interface Subscription {
 void unsubscribe(); 
 boolean isUnsubscribed();
 }
  19. Observable creation Observable.create(new Observable.OnSubscribe<String>() {
 @Override public void call(Subscriber<? super

    String> subscriber) { 
 }
 }); subscriber.onNext("Hello DevFest LA 2016"); subscriber.onCompleted();
  20. Observable creation Observable.create(new Observable.OnSubscribe<String>() {
 @Override public void call(Subscriber<? super

    String> subscriber) {
 try {
 subscriber.onNext(expensiveOperation());
 } catch (IOException e) {
 subscriber.onError(e);
 }
 subscriber.onCompleted();
 }
 });
  21. Concurrency • Where to put subscribeOn and observeOn? • Should

    only be invoked by the the final subscriber.
  22. Operators Observable.from(schedules)
 
 
 .map(schedule -> schedule.speaker) .filter(speaker -> "Chat

    Haase".equals(speaker.name)) .flatMap(speaker -> getGitHubProfile(speaker.gitHubUrl))
  23. Operators Observable.from(schedules) .map(schedule -> schedule.speaker) .filter(speaker -> "Chat Haase".equals(speaker.name)) .flatMap(speaker

    -> getGitHubProfile(speaker.gitHubUrl) .zipWith(getLinkedInProfile(speaker.linkedInUrl), (gitHubProfile, linkedInProfile) -> new Profile()));
  24. Reusing operators Observable.from(schedules)
 .compose(new Transformer<Schedule, GitHubStatus>() {
 @Override public Observable<GitHubStatus>

    call(Observable<Schedule> source) {
 return source.map(schedule -> schedule.speaker)
 .flatMap(speaker -> getGitHubProfile(speaker.gitHubUrl));
 }
 }); .compose()!
  25. Error handling • Don’t care then just log it •

    onErrorReturn/onErrorResumeNext for default values
  26. Lifecycle • RxJava is unaware of Android lifecycle • Add

    multiple Subscriptions into a CompositeSubscription • Call .clear() when lifecycle ends • Don’t call .unsubscribe
  27. Unit test • Legacy code is code without tests. •

    TestSubscriber • TestScheduler
  28. Unit test • Legacy code is code without tests. •

    TestSubscriber • TestScheduler • A great way to lean RxJava
  29. Plugins • RxJavaHooks in 1.x • Fine grained control for

    changing default behavior • Override Scheulders.IO/MainThreadScheudler in unit tests
  30. Plugins • RxJavaHooks in 1.x • Fine grained control for

    changing default behavior • Override Scheulders.IO/MainThreadScheudler in unit tests • onError hook
  31. RxJava 2 • Matches Reactive Stream specification • No longer

    accepts null • Observable -> Flowable or Observable • Single/Completable remains the same • Maybe • Subscription -> Disposable
  32. References • RxJava: https://github.com/ReactiveX/RxJava • RxAndroid: https://github.com/ReactiveX/RxAndroid • RxBinding: https://github.com/JakeWharton/RxBinding

    • Introduction to Rx: http://www.introtorx.com/ • Demystifying RxJava Subscribers by Jake Wharton: http://jakewharton.com/ demystifying-rxjava-subscribers/ • What’s different in 2.0: https://github.com/ReactiveX/RxJava/wiki/What's- different-in-2.0 • Reactive Programming with RxJava By Tomasz Nurkiewicz, Ben Christensen • Advanced RxJava by David Karnok : http://akarnokd.blogspot.com/