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
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 { public void call(T value); }
RxJava - Creating a cold observable Observable.create(new Observable.OnSubscribe() { @Override public void call(Subscriber super String> subscriber) { // Do some more stuff subscriber.onNext("Hello, GDG Bucharest!"); subscriber.onCompleted(); } });
RxJava - Creating a cold observable Observable.create(new Observable.OnSubscribe() { @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(); });
Schedulers Mechanism to switch the threads on which steps get executed Schedulers.computation(); Schedulers.io(); Schedulers.immediate(); AndroidSchedulers.mainThread();
Event Bus - the idea Decouple event emitters and consumers Steps: Subject + Subscriber Subject lives “forever” Anyone can post events Observers subscribe when needed
Event Bus - How? Subjects to the rescue class RxBus { private final Subject mBus = new SerializedSubject<>(PublishSubject.create()); public void post(MyEvent e) { mBus.onNext(e); } public Observable toObserverable() { return mBus.asObservable(); } }
Event Bus - How? Sending events: rxBus.post(new MyEvent()); Listening for events: rxBus.toObserverable() .subscribe(event -> { // do something with the event });
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
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
Cache prefetching - How? Observable cacheDataLoader = loadCacheData(); Observable freshDataLoader = loadFreshData(); Observable.concat(cacheDataLoader, freshDataLoader) .observeOn(AndroidSchedulers.mainThread()) .subscribe( data -> { // Update the UI with the available data mAdapter.setNewData(data); });
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
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
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); } );
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”
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