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

RxJava Basics

RxJava Basics

An introduction to ReactiveX focused on Java & Android examples. Covers basic code samples for RxJava and a set of use-cases for the pattern.

Cosmin Stefan-Dobrin

February 03, 2016
Tweet

Other Decks in Technology

Transcript

  1. Contents Can I use ReactiveX in Java & Android? RxJava

    - how does it look like? What can I do with it in Android? What should I keep in mind?
  2. RxJava - What is it this about? Java implementation of

    Reactive Extensions Zero dependencies Relatively small footprint (<800KB) Stable (1.1.0 - December 2015) Support for Scala, Groovy, Clojure, Kotlin
  3. Lambda Expressions Pass functionality as argument Short implementation of single-method

    anonymous classes Type inference (argumentList) -> { /* code */ }
  4. Lambda Expressions - Examples mTextView.setOnClickListener(new View.OnClickListener() { @Override public void

    onClick(View v) { // perform action } }); new Thread(new Runnable() { @Override public void run() { System.out.println("Hello World!"); } }); mTextView.setOnClickListener(v -> { // perform action }); new Thread(() -> { System.out.println("Hello World!"); });
  5. Retrolambda Java 8 Lambda functionality down to Java 5 Gradle

    integration for Android Editing support in Android Studio
  6. RxJava - Starting simple (2) Observable<String> observable = Observable.just("Hello, GDG

    Bucharest!"); observable.subscribe(new Observer<String>() { @Override public void onNext(String value) { System.out.println(value); } @Override public void onCompleted() { System.out.println("The End!"); } @Override public void onError(Throwable e) { System.err.println("Ooops, I did it again!"); } });
  7. RxJava - Making it simpler We can just specify a

    subset of the actions observable.subscribe(onNextAction, onErrorAction, onCompleteAction); observable.subscribe(onNextAction, onErrorAction); observable.subscribe(onNextAction); public interface Action1<T> { public void call(T value); }
  8. RxJava meets lambda Observable.just("Hello, GDG Bucharest!") .subscribe(new Action1<String>() { @Override

    public void call(String value) { System.out.println(value); } }); Observable.just("Hello, GDG Bucharest!") .subscribe(s -> System.out.println(s))
  9. Transforming Observable.just("Hello, GDG Bucharest!") .map(new Func1<String, Integer>() { @Override public

    Integer call(String s) { return s -> s.hashCode(); } }) .subscribe(new Action1<Integer>() { @Override public void call(Integer hash) { System.out.println("The hash is: " + hash) } });
  10. Transforming Observable.just("Hello, GDG Bucharest!") .map(new Func1<String, Integer>() { @Override public

    Integer call(String s) { return s -> s.hashCode(); } }) .subscribe(new Action1<Integer>() { @Override public void call(Integer hash) { System.out.println("The hash is: " + hash) } }); Observable.just("Hello, GDG Bucharest!") .map(s -> s.hashCode()) .subscribe(hash -> System.out.println("The hash is: " + hash));
  11. Taking it to the next step Observable.just("Hello, GDG Bucharest!") .map(s

    -> s + ";Hello, World!") .flatMap(s -> { String[] pieces = s.split(";"); return Observable.from(pieces); }) .map(s -> s + "!!") .subscribe(s -> System.out.println(s));
  12. Taking it to the next step Observable.just("Hello, GDG Bucharest!") .map(s

    -> s + ";Hello, World!") .flatMap(s -> { String[] pieces = s.split(";"); return Observable.from(pieces); }) .map(s -> s + "!!") .subscribe(s -> System.out.println(s)); Outputs: Hello, GDG Bucharest!!! Hello, World!!!
  13. RxJava - Creating a cold observable Observable.create(new Observable.OnSubscribe<String>() { @Override

    public void call(Subscriber<? super String> subscriber) { // Do some more stuff subscriber.onNext("Hello, GDG Bucharest!"); subscriber.onCompleted(); } });
  14. RxJava - Creating a cold observable Observable.create(new Observable.OnSubscribe<String>() { @Override

    public void call(Subscriber<? super String> subscriber) { // Do some more stuff subscriber.onNext("Hello, GDG Bucharest!"); subscriber.onCompleted(); } }); Observable.create(subscriber -> { // Do some more stuff subscriber.onNext("Hello, GDG Bucharest!"); subscriber.onCompleted(); });
  15. Schedulers Mechanism to switch the threads on which steps get

    executed Schedulers.computation(); Schedulers.io(); Schedulers.immediate(); AndroidSchedulers.mainThread();
  16. Schedulers - Power overwhelming public Observable<Bitmap> loadImage(String url); ... loadImage(testUrl)

    .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(bitmap -> mImageView.setImageBitmap(bitmap));
  17. Event Bus - the idea Decouple event emitters and consumers

    Steps: Subject + Subscriber Subject lives “forever” Anyone can post events Observers subscribe when needed
  18. Event Bus - How? Subjects to the rescue class RxBus

    { private final Subject<MyEvent, MyEvent> mBus = new SerializedSubject<>(PublishSubject.create()); public void post(MyEvent e) { mBus.onNext(e); } public Observable<MyEvent> toObserverable() { return mBus.asObservable(); } }
  19. Event Bus - How? Sending events: rxBus.post(new MyEvent()); Listening for

    events: rxBus.toObserverable() .subscribe(event -> { // do something with the event });
  20. Instant search throttling - the idea Wait until text has

    “stabilized” Steps: Observable + Debounce operator Watcher for text change events on InputTextView Conversion to observable events Debounce for limiting
  21. Instant search throttling - How? public Observable<TextChangeEvent> observableForTextViewChangeEvents(TextView tv); ...

    observableForTextViewChangeEvents(mTextView) // make sure it’s stable .debounce(400, TimeUnit.MILLISECONDS) // perform the search .map(textChangeEvent -> { return performSearch(textChangeEvent); }) .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) // and finally update the UI accordingly .subscribe(searchResults -> { updateUI(searchResults) });
  22. Load both from cache and from network Quickly show preliminary

    results from cache Steps: Concat / Merge operator Create observables for both types of load Merge the results and handle in common way Cache prefetching - the idea
  23. Cache prefetching - How? Observable<Data> cacheDataLoader = loadCacheData(); Observable<Data> freshDataLoader

    = loadFreshData(); Observable.concat(cacheDataLoader, freshDataLoader) .observeOn(AndroidSchedulers.mainThread()) .subscribe( data -> { // Update the UI with the available data mAdapter.setNewData(data); });
  24. Generic API / library - sync vs async Build a

    versatile API / library supporting both async or sync use Steps: Observable + subscribeOn()/observeOn() Expose Cold Observables (perform work upon subscription) Can be run either synchronously or asynchronously
  25. Generic API - sync vs async // Perform task on

    the current thread mMyFancyApi.doFancyTask() .subscribe(result -> doSomething());
  26. Generic API - sync vs async // Perform task on

    the current thread mMyFancyApi.doFancyTask() .subscribe(result -> doSomething()); // Perform task asynchronously mMyFancyApi.doFancyTask() .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(result -> doSomethingElse());
  27. Retrofit and RxJava, sitting in a tree Simplify network calls

    to APIs Steps: Retrofit + Operators + subscribeOn()/observeOn() Use the Rx-aware Retrofit calls Run network calls on Schedulers.io() Chain processing Switch back to main thread for UI updates
  28. Retrofit and RxJava, sitting in a tree mWebService.fetchPosts() // Split

    posts list to individual items .flatMap(posts -> Observable.from(posts)) // Process each item .doOnNext(post -> storeToLocalDatabase(post)) // Take just the last post .last() // Configure threads properly .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) // Handle final results .subscribe(post -> { updateUI(post); }, (error) -> { Log.e(TAG, "Network error!", error); } );
  29. Android lifecycles Take Activity/Fragment lifecycle into account Care when outliving

    the bound components Unsubscribe when result not needed anymore RxLifecyle to the rescue “Lifecycle handling APIs for Android apps using RxJava”
  30. Parting thoughts Can certainly simplify certain scenarios Power comes from

    chaining operations Thread switching easier Synchronization still an issues Not a silver bullet Don’t overuse - performance can become an issue
  31. Rx enabled Projects https://github.com/square/retrofit - REST service wrapper https://github.com/jersey/jersey -

    REST service wrapper https://github.com/square/sqlbrite - Reactive database wrapper https://github.com/ReactiveX/RxNetty - Async network framework https://github.com/davidmoten/rtree - RTree implementation https://github.com/Netflix/Hystrix - Latency and fault tolerance library https://github.com/mulab/rx-realm - Mobile database system & many more....