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

RxJava: a Java implementation of Reactive Extentions

RxJava: a Java implementation of Reactive Extentions

A short introduction to Reactive Extentions for the JVM

D90102aaed6eb7403f745ad75138e777?s=128

Alessandro Calzavara

September 29, 2015
Tweet

Transcript

  1. RxJava a Java implementation of Reactive Extentions HACKATRON TALK

  2. DrAL3X Mobile Developer at 
 Spreaker.com DrAL3X on ALESSANDRO CALZAVARA

  3. A Library for composing asynchronous and event-based programming using observable

    sequences for the Java VM RXJAVA WHAT IS
  4. "It extends the observer pattern to support sequences of data

    and/or events and adds operators that allow you to compose sequences together declaratively while abstracting away concerns about things like low-level threading, synchronization, thread-safety, concurrent data structures, and non-blocking I/O." @ ReactiveX.io “
  5. OBSERVER PATTERN THE BASICS OF Observer: • handle notifications Subject:

    • register/unregister observers • notify observers
  6. WHY USING RX

  7. SIMPLE API EVERYTHING BEGINS WITH A public Data getData(); Owner

    of API should retain control of concurrency behaviour. User should simply not care how it work behind.
  8. CHANGE API CHANGE INTERACTION BY single items multiple items synch

    T getData() Iterable<T> getData() asynch Future<T> getData() Observable<T> getData()
  9. ITERABLE and OBSERVABLE DUALITY BETWEEN Iterable Observable pull push T

    next() onNext(T) throws Exception onError(Exception) returns onCompleted()
  10. T getData() SYNC SINGLE ITEM String s = getData(args); if

    (s.equals(x)) { // do something } else { // do something else }
  11. Iterable<T> getData() SYNC MULTIPLE ITEMS Iterable<String> values = getData(args); for

    (String s : values) { if (s.equals(x)) { // do something } else { // do something else } }
  12. Future<T> getData() ASYNC SINGLE ITEM Future<String> s = getData(args); if

    (s.get().equals(x)) { // do something } else { // do something else }
  13. FUTURES REMOVE BLOCKING WITH Future<String> d = getData(args); Futures.addCallback(d, new

    FutureCallback<String> { public void onSuccess(String s) { if (s.equals(x)) { // do something } else { // do something else } } }, executor);
  14. COMPOSABLE FUTURE REMOVE BLOCKING WITH Future<String> d = getData(args); d.map({

    s -> if (s.equals(x)) { // do something } else { // do something else } }); Only Java 8+ or Scala
  15. Observable<T> getData() ASYNC MULTIPLE ITEMS Observable<String> d = getData(args); d.map({

    s -> if (s.equals(x)) { // do something } else { // do something else } });
  16. OBSERVABLE API MORE FLEXIBLE One interface to rule them all.

    Client code treats all interactions with the API as ASYNCHRONOUS. The API implementation chooses whether something is BLOCKING or NON- BLOCKING and WHAT resources it uses.
  17. HOW TO CREATE AN OBSERVABLE

  18. Observable.create(new OnSubscribe<String>() { @Override public void call(Subscriber<String> subscriber) { try

    { subscriber.onNext("Hello"); subscriber.onCompleted(); } catch (Exception e) { subscriber.onError(e); } } })
  19. ASYNC OBSERABLE WITH MULTIPLE VALUES

  20. Observable<Image> getTopImages() { return Observable.create(new OnSubscribe<Image>() { @Override public void

    call(Subscriber<Image> subscriber) { try { for (id in imageIds) { Image i = …do network call… subscriber.onNext(i); } subscriber.onCompleted(); } catch (Exception e) { subscriber.onError(e); } } })
  21. ASYNCHRONOUS OBSERVER

  22. getTopImages().subscribe(new Observer<Image>() { void onNext(Image image) { println("Image: " +

    image.getImageId()); } void onError(Exception e) { println("Error"); e.printStackTrace(); } void onCompleted() { println("Completed"); } });
  23. Transform: map, flatmap, reduce, scan Filter: take, skip, sample, takeWhile,

    filter Combine: concat, merge, zip, combineLatest,
 multicast, publish, cache, refCount Concurrency: observeOn, subscribeOn Error handling: onErrorReturn, onErrorResume OPERATORS COMPOSABLE FUNCTIONS AKA
  24. MERGE COMBINING VIA

  25. ZIP COMBINING VIA

  26. ERRORS HANDLING

  27. REAL WORLD EXAMPLE

  28. this._episodeRepository.getEpisodeWithSegments(episodeId) .map(new Func1<Episode, Episode>() { @Override public Episode call(Episode episode)

    { // Check if EPISODE segment is available… } }) .flatMap(new Func1<Episode, Observable<Episode>>() { @Override public Observable<Episode> call(final Episode episode) { // Write episode to database… } }) .subscribeOn(RxSchedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(new Subscriber<Episode>() { // Add download to queue or notify error… });
  29. MAP CHECK IF AUDIO SEGMENT IS AVAILABLE .map(new Func1<Episode, Episode>()

    { @Override public Episode call(Episode episode) { // Check if EPISODE segment is available String downloadUrl = null; for (AudioSegment segment : episode.getSegments()) { if (segment.getType() == AudioSegment.Type.EPISODE && segment.getHttpUrl() != null) { downloadUrl = segment.getHttpUrl(); break; } }
  30. MAP CHECK IF AUDIO SEGMENT IS AVAILABLE episode.getSegments()) { if

    (segment.getType() == AudioSegment.Type.EPISODE && segment.getHttpUrl() != null) { downloadUrl = segment.getHttpUrl(); break; } } if (downloadUrl == null) { throw new IllegalArgumentException(…); } // Update episode property episode.setOfflineUrl(downloadUrl); episode.setOfflineFilepath(_destinationFileForEpisode( episode.getEpisodeId()).getAbsolutePath()); episode.setOfflineAt(createdAt); episode.setOfflineStatus(Episode.OfflineStatus.WAITING); return episode; } })
  31. FLATMAP WRITE EPISODE TO DATABASE WITH .flatMap(new Func1<Episode, Observable<Episode>>() {

    @Override public Observable<Episode> call(final Episode episode) { // Write episode to database return _offlineRepository .addOfflineEpisodeDatabase(ep) .map(new Func1<Boolean, Episode>() { @Override public Episode call(Boolean added) { return ep; } }); }})
  32. SUBSCRIBE HANDLE ERROR OR SUCCESS ON .subscribe(new Subscriber<Episode>() { @Override

    public void onError(Throwable e) { // Notify failure … } @Override public void onNext(Episode episode) { // Notify success and add to download queue … } });
  33. Interactions with the API are ASYNCHRONOUS and DECLARATIVE API implementation

    controls CONCURRENCY BEHAVIOUR The only "rule" is: DON'T MUTATE STATE OUTSIDE OF FUNCTION LESSONS LEARNED TO SUM UP
  34. ReactiveX: http://reactivex.io What does it means to be Reactive? https://www.youtube.com/watch?

    v=sTSQlYX5DU0 RxJava @ Github: https://github.com/ReactiveX/RxJava Observer Pattern: https://en.wikipedia.org/wiki/ Observer_pattern Marbles diagrams: http://rxmarbles.com/
  35. THANK YOU