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

Reactive programming on Android

Reactive programming on Android

Lecture on Reactive programming on Android, mDevCamp 2016.
A practical guide to using RxJava on Android. Tips for improving your app architecture with reactive programming. What are the advantages and disadvantages of using RxJava over standard architecture? And how to connect with other popular Android libraries?

Tomáš Kypta

June 17, 2016
Tweet

More Decks by Tomáš Kypta

Other Decks in Programming

Transcript

  1. What’s RxJava ▪ combination of – observer pattern – iterator

    pattern – functional programming ▪ composable data flow ▪ push concept
  2. Key Methods ▪ subscribers can be replaced with Action parameters

    someObservable.subscribe( onNextAction, onErrorAction, onCompleteAction );
  3. Key Methods ▪ we often ignore onError() and onComplete() ▪

    risk of crashes when error occurs someObservable.subscribe( onNextAction );
  4. What is RxJava good for? ▪ Async composition – nested

    API calls – AsyncTask callback hell – There’s no way to do it right!
  5. Example Observable.just("Hello, world!") .subscribe(new Subscriber<String>() { @Override public void onCompleted()

    {…} @Override public void onError(Throwable e) {…} @Override public void onNext(String s) { Timber.d(s); } });
  6. Tip #1 - use Retrolambda Observable.just("Hello, world!") .subscribe(s -> Timber.d(s));

    Observable.just("Hello, world!") .subscribe(new Action1<String>() { @Override public void call(String s) { Timber.d(s); } });
  7. Observer vs. Subscriber ? myObservable .subscribe(new Observer<String>() { @Override public

    void onCompleted() {} @Override public void onError(Throwable e) {} @Override public void onNext(String s) {} }); myObservable .subscribe(new Subscriber<String>() { @Override public void onCompleted() {} @Override public void onError(Throwable e) {} @Override public void onNext(String s) {} });
  8. Observer vs. Subscriber ▪ simpler unsubscribe() with Subscriber myObservable .subscribe(new

    Subscriber<String>() { @Override public void onCompleted() { unsubscribe(); } @Override public void onError(Throwable e) {} @Override public void onNext(String s) {} });
  9. map vs. flatMap vs. concatMap ▪ map – A ->

    B – one in, one out ▪ flatMap – A -> Observable<B> – map + flatten ▪ concatMap – ordered flatMap
  10. Threading ▪ subscribeOn(Scheduler) ▪ subscribes to Observable on the Scheduler

    ▪ observeOn(Scheduler) ▪ Observable emits on the Scheduler
  11. computation() vs. io() ▪ io() – unbounded thread pool –

    I/O operations ▪ computation() – bounded thread pool – CPU intensive computational work
  12. Observable methods ▪ extra actions ▪ doOnNext() ▪ doOnError() ▪

    doOnSubscribe() ▪ doOnUnsubscribe() ▪ …
  13. Bridging non-Rx APIs ▪ just() private Object getData() {...} public

    Observable<Object> getObservable() { return Observable.just(getData()); }
  14. Tip #2 - defer() ▪ use defer() to avoid immediate

    execution private Object getData() {...} public Observable<Object> getObservable() { return Observable.defer( () -> Observable.just(getData()) ); }
  15. Subjects ▪ Observable & Observer ▪ bridge between non-Rx API

    ▪ stateful – terminal state ▪ don’t pass data after onComplete()/onError()
  16. Subjects ▪ cannot be reused – always create a new

    instance when subscribing to an Observable
  17. RxLifecycle ▪ auto unsubscribe based on Activity/Fragment lifecycle myObservable .compose(RxLifecycle.bindUntilEvent(lifecycle,

    ActivityEvent.DESTROY)) .subscribe(); myObservable .compose(RxLifecycle.bindActivity(lifecycle)) .subscribe();
  18. RxLifecycle ▪ obtain ActivityEvent or FragmentEvent by: A. rxlifecycle-components +

    subclass RxActivity, RxFragment B. Navi + rxlifecycle-navi C. Write it yourself
  19. RxLifecycle public class MyActivity extends RxActivity { @Override public void

    onResume() { super.onResume(); myObservable .compose(bindToLifecycle()) .subscribe(); } }
  20. RxLifecycle public class MyActivity extends NaviActivity { private final ActivityLifecycleProvider

    provider = NaviLifecycle.createActivityLifecycleProvider(this); @Override public void onResume() { super.onResume(); myObservable .compose(provider.bindToLifecycle()) .subscribe(…); } }
  21. RxLifecycle public class MainActivityFragment extends Fragment { BehaviorSubject<FragmentEvent> mLifecycleSubject =

    BehaviorSubject.create(); @Override public void onResume() { super.onResume(); RxView.clicks(vBtn) .compose(RxLifecycle.bindUntilEvent(mLifecycleSubject, FragmentEvent.PAUSE)) .doOnUnsubscribe(() -> Timber.i("onUnsubscribe")) .subscribe(…); } }
  22. RxLifecycle public class MainActivityFragment extends Fragment { BehaviorSubject<FragmentEvent> mLifecycleSubject =

    BehaviorSubject.create(); @Override public void onResume() { super.onResume(); RxView.clicks(vBtn) .compose(RxLifecycle.bindUntilEvent(mLifecycleSubject, FragmentEvent.PAUSE)) .doOnUnsubscribe(() -> Timber.i("onUnsubscribe")) .subscribe(…); } @Override public void onPause() { super.onPause(); Timber.i("onPause"); mLifecycleSubject.onNext(FragmentEvent.PAUSE); } }
  23. RxBinding RxView.clicks(vBtnSearch) .subscribe( v -> { Intent intent = new

    Intent(getActivity(), SearchActivity.class); startActivity(intent); } );
  24. RxBinding ▪ compile ‘com.jakewharton.rxbinding:rxbinding:0.4.0' ▪ compile ‘com.jakewharton.rxbinding:rxbinding-support-v4:0.4.0' ▪ compile ‘com.jakewharton.rxbinding:rxbinding-appcompat-v7:0.4.0'

    ▪ compile ‘com.jakewharton.rxbinding:rxbinding-design:0.4.0' ▪ compile ‘com.jakewharton.rxbinding:rxbinding-recyclerview-v7:0.4.0' ▪ compile 'com.jakewharton.rxbinding:rxbinding-leanback-v17:0.4.0'
  25. Retrofit – onNext() with Response, then onComplete() – onError() in

    case of error @GET("/data") Observable<Response> getData( @Body DataRequest dataRequest);