Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

RxJava in practice

1,093 views

Published on

Slides for a workshop about RxJava & RxAndroid delivered in Codemotion 2015.

Published in: Technology

RxJava in practice

  1. 1. MADRID · NOV 27-28 · 2015 RxJava in practice Javier Gamarra
  2. 2. MADRID · NOV 27-28 · 2015 http://kcy.me/29crj (slides) & http://kcy.me/296bu (commits)
  3. 3. MADRID · NOV 27-28 · 2015 Environment Eclipse | Android Studio (RxAndroid) RxJava.jar [Java 8] || [Retrolambda] :P
  4. 4. MADRID · NOV 27-28 · 2015 Environment Android Studio: compile 'io.reactivex:rxandroid:1.0.1' compile 'io.reactivex:rxjava:1.0.16' Eclipse: ● Copy jars to lib/ and add jar in project
  5. 5. MADRID · NOV 27-28 · 2015 Github ● http://kcy.me/296bu ● koans ● código ● commit a commit ● Podéis preguntarme en cualquier momento
  6. 6. MADRID · NOV 27-28 · 2015 Who? Javier Gamarra / @nhpatt @liferay @cyliconvalley / @agilespain
  7. 7. MADRID · NOV 27-28 · 2015 Ask! Please? Pretty please? Please pretty please with sugar on top?
  8. 8. MADRID · NOV 27-28 · 2015 Background?
  9. 9. MADRID · NOV 27-28 · 2015 Why?
  10. 10. MADRID · NOV 27-28 · 2015 Why? (in java) multithreading is hard futures are complicated callbacks are hell
  11. 11. MADRID · NOV 27-28 · 2015 Rx comes to the rescue!
  12. 12. MADRID · NOV 27-28 · 2015 a library to represent any operation as an asynchronous data stream on any thread, declaratively composed, and consumed by multiple objects
  13. 13. MADRID · NOV 27-28 · 2015 a library
  14. 14. MADRID · NOV 27-28 · 2015 A library? Extensions to .NET framework Netflix
  15. 15. MADRID · NOV 27-28 · 2015 Libraries are tools If all you have is a hammer, everything looks like a nail
  16. 16. MADRID · NOV 27-28 · 2015 a library to model Observables & Subscribers
  17. 17. MADRID · NOV 27-28 · 2015 Observables and Subscribers An Observable emits items. A Subscriber consumes those items.
  18. 18. MADRID · NOV 27-28 · 2015 Observer pattern?
  19. 19. MADRID · NOV 27-28 · 2015 My very first observable Observable<String> myObs = Observable. create(new Observable. OnSubscribe<String>() { @Override public void call(Subscriber<? super String> subscriber) { subscriber.onNext( "Hi!"); subscriber.onCompleted(); } });
  20. 20. MADRID · NOV 27-28 · 2015 My very first subscriber Subscriber<String> mySubs = new Subscriber<String>() { @Override public void onCompleted() { } @Override public void onError(Throwable throwable) { } @Override public void onNext(String s) { System. out.println(s); } };
  21. 21. MADRID · NOV 27-28 · 2015 My very first subscription myObs.subscribe(mySubs);
  22. 22. MADRID · NOV 27-28 · 2015 A bit verbose... Let’s simplify with Java8 and RxJava ● lamdbas ● Observable.just ● .subscribe()
  23. 23. MADRID · NOV 27-28 · 2015 That’s better... Observable .just("Hi!") .subscribe(System.out::println);
  24. 24. MADRID · NOV 27-28 · 2015 Why? More than the observer pattern ● Observables only emit when someone listening ● OnFinished ● OnError
  25. 25. MADRID · NOV 27-28 · 2015 Let’s use those differences subscribe admits 3 parameters ● OnNext ● OnFinished ● OnError
  26. 26. MADRID · NOV 27-28 · 2015 You said “items” Observable.from admits a list of elements
  27. 27. MADRID · NOV 27-28 · 2015 Ok, let’s recap… Iterators?
  28. 28. MADRID · NOV 27-28 · 2015 Iterators? ● Iterators are pull and synchronous ● Subscribers are push and asynchronous
  29. 29. MADRID · NOV 27-28 · 2015 to represent any operation as an “asynchronous data stream”
  30. 30. MADRID · NOV 27-28 · 2015 Everything is a stream
  31. 31. MADRID · NOV 27-28 · 2015 Everything is a stream We can model everything as a stream
  32. 32. MADRID · NOV 27-28 · 2015 Everything is a stream A network call is also a stream Like using retrofit with this API
  33. 33. MADRID · NOV 27-28 · 2015 “declaratively composed”
  34. 34. MADRID · NOV 27-28 · 2015 Operators
  35. 35. MADRID · NOV 27-28 · 2015 Operators Transform a stream rxmarbles and android app
  36. 36. MADRID · NOV 27-28 · 2015 Operators Map
  37. 37. MADRID · NOV 27-28 · 2015 Map List<String> severalThings = Arrays.asList("1", "2"); Observable.from(severalThings) .map((s) -> “Element “ + s) .subscribe(System.out::println);
  38. 38. MADRID · NOV 27-28 · 2015 Map We can return another type: List<String> severalThings = Arrays.asList("1", "2"); Observable.from(severalThings) .map(Integer::valueOf) .subscribe(System.out::println);
  39. 39. MADRID · NOV 27-28 · 2015 Map Let’s do the same with our repos… And… I can’t because we return a List And using Observable.from… NOP
  40. 40. MADRID · NOV 27-28 · 2015 Flatmap Flatmap Obs -> elements
  41. 41. MADRID · NOV 27-28 · 2015 Flatmap service.listRepos("nhpatt") .flatMap(Observable::from) .map(Repo::getName) .map((s) -> s.replace("-", " ")) .subscribe(System.out::println);
  42. 42. MADRID · NOV 27-28 · 2015 Flatmap Concatmap -> ordered flatmap
  43. 43. MADRID · NOV 27-28 · 2015 Filter service.listRepos("nhpatt") .flatMap(Observable::from) .map(Repo::getName) .map((s) -> s.replace("-", " ")) .filter((s) -> s.startsWith("Android")) .subscribe(System.out::println);
  44. 44. MADRID · NOV 27-28 · 2015 Scan & old code service.listRepos("nhpatt") .flatMap(Observable::from) .map(Repo::getName) .map((s) -> s.replace("-", " ")) .filter((s) -> s.startsWith("Android")) .take(2) .map(String::length) .scan((x, y) -> x * y) .subscribe(System.out::println);
  45. 45. MADRID · NOV 27-28 · 2015 Scan & old code (l) -> { int result = 0; int i = 0; int oldLength = 1; for (Repo repo : l) { String name = repo.getName(); String replacedName = name.replace( "-", " "); if (replacedName.startsWith( "Android") && i < 2) { result = replacedName.length() * oldLength; oldLength = result; System.out.println(result); i++; } } return result;
  46. 46. MADRID · NOV 27-28 · 2015 Operators ● merge ● flatMap ● zip Nice things™ : parallel jobs!
  47. 47. MADRID · NOV 27-28 · 2015 Zipping requests Observable<Repo> repo = service.listRepos("nhpatt") .flatMap(Observable::from) .take(1); Observable<Commit> commit = service.listCommits("nhpatt", "Android") .flatMap(Observable::from) .take(1); Observable.zip(repo, commit, this::updateCommit).subscribe (repo1 -> { System.out.println(repo1.getCommit().getUrl()); });
  48. 48. MADRID · NOV 27-28 · 2015 Operators Amazing documentation ● Async ● Blocking ● Combining ● Conditional ● Error handling ● Filtering ● Mathematical ● Creation ● String ● Transforming ● Utility
  49. 49. MADRID · NOV 27-28 · 2015 Subscribers are asynchronous? No, not really
  50. 50. MADRID · NOV 27-28 · 2015 “on any thread”
  51. 51. MADRID · NOV 27-28 · 2015 Schedulers!
  52. 52. MADRID · NOV 27-28 · 2015 Schedulers I define an API declaratively and later in the implementation run it: asynchronously or in a separate Thread or in a Threadpool or synchronously ...
  53. 53. MADRID · NOV 27-28 · 2015 Schedulers .subscribeOn(Schedulers...) .observeOn(Schedulers...) ● io ● computation ● newThread ● trampoline ● test
  54. 54. MADRID · NOV 27-28 · 2015 Schedulers service.listRepos("nhpatt") .subscribeOn(Schedulers.immediate()) .observeOn(Schedulers.immediate()) .subscribe(System.out::println);
  55. 55. MADRID · NOV 27-28 · 2015 Schedulers RxJava operators have default threads Interval?
  56. 56. MADRID · NOV 27-28 · 2015 Use cases?
  57. 57. MADRID · NOV 27-28 · 2015 Use cases ● Autocomplete with debounce | sample… ● Accumulate calls with buffer... ● Polling with timeout | window… ● Form Validation with combineLatest… ● Retrieve data fast from cache | network call with concat | merge… ● Button click with delay, listen on other thread
  58. 58. MADRID · NOV 27-28 · 2015 Android?
  59. 59. MADRID · NOV 27-28 · 2015 Why?
  60. 60. MADRID · NOV 27-28 · 2015 Why? (in android) Main/UI thread and background problem ● Can’t do heavy tasks on UI ● Can’t update view on background ● AsyncTasks are bad ● Handlers can leak
  61. 61. MADRID · NOV 27-28 · 2015 How RxAndroid helps?
  62. 62. MADRID · NOV 27-28 · 2015 Android schedulers service.listRepos("nhpatt") .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(newRepos -> { repos.addAll(newRepos); adapter.notifyDataSetChanged(); });
  63. 63. MADRID · NOV 27-28 · 2015 Orientation Problem Orientation Problem ● onCreate gets called again ● state is lost
  64. 64. MADRID · NOV 27-28 · 2015 Orientation Problem Programmer’s job: ● Store/Restore state ● Restore view ● Call again the user task? ● Wait until it finishes?
  65. 65. MADRID · NOV 27-28 · 2015 How RxAndroid helps?
  66. 66. MADRID · NOV 27-28 · 2015 Orientation Problem Observable is easy to persist (retain | singleton) Observable can continue (cache and retry) RxLifecycle
  67. 67. MADRID · NOV 27-28 · 2015 Orientation Problem Observable<List<Repo>> github = RetrofitService. getGithub() .listRepos("nhpatt") .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .cache();
  68. 68. MADRID · NOV 27-28 · 2015 More Android Lifecycle (RxLifecyle) Views (RxBinding)
  69. 69. MADRID · NOV 27-28 · 2015 But...
  70. 70. MADRID · NOV 27-28 · 2015 But... Subscriptions leak memory :’( We have to call to unsubscribe (CompositeSubscription helps) And don’t include references to the object/activity
  71. 71. MADRID · NOV 27-28 · 2015 Easy to unsubscribe @Override protected void onStop() { super.onStop(); subscription.unsubscribe(); } .isUnsubscribed() :(
  72. 72. MADRID · NOV 27-28 · 2015 Let’s recap
  73. 73. MADRID · NOV 27-28 · 2015 a library to represent any operation as an asynchronous data stream on any thread, declaratively composed, and consumed by multiple objects
  74. 74. MADRID · NOV 27-28 · 2015 a library to represent any operation as an observable on any thread, declaratively composed, and consumed by multiple objects
  75. 75. MADRID · NOV 27-28 · 2015 a library to represent any operation as an observable with schedulers declaratively composed, and consumed by multiple objects
  76. 76. MADRID · NOV 27-28 · 2015 a library to represent any operation as an observable with schedulers and operators and consumed by multiple objects
  77. 77. MADRID · NOV 27-28 · 2015 a library to represent any operation as an observable with schedulers and operators listened by subscribers
  78. 78. MADRID · NOV 27-28 · 2015 But...
  79. 79. MADRID · NOV 27-28 · 2015 But... ● Learning curve ● Hard to debug (Frodo library) ● Backpressure
  80. 80. MADRID · NOV 27-28 · 2015 Questions?
  81. 81. MADRID · NOV 27-28 · 2015 Where to know more... ● reactivex.io (amazing docs) ● RxJava wiki ● Dan Lew ● Use cases
  82. 82. MADRID · NOV 27-28 · 2015 Where to know more... nhpatt (twitter | github | email | slack) I’ll do anything for good votes
  83. 83. MADRID · NOV 27-28 · 2015 Feedback Click here :P
  84. 84. MADRID · NOV 27-28 · 2015 RxJava in practice Javier Gamarra
  85. 85. MADRID · NOV 27-28 · 2015 Other interesting operators...
  86. 86. MADRID · NOV 27-28 · 2015 Take service.listRepos("nhpatt") .flatMap(Observable::from) .map(Repo::getName) .map((s) -> s.replace("-", " ")) .filter((s) -> s.startsWith("Android")) .take(2) .subscribe(System.out::println);
  87. 87. MADRID · NOV 27-28 · 2015 Operators distinctUntilChanged compose
  88. 88. MADRID · NOV 27-28 · 2015 Errors?
  89. 89. MADRID · NOV 27-28 · 2015 onError() is called if an Exception is thrown at any time (this is cool) The operators don't have to handle the Exception No more callbacks Errors
  90. 90. MADRID · NOV 27-28 · 2015 Errors And we can customize the flow: onErrorResumeNext onErrorReturn retry ...
  91. 91. MADRID · NOV 27-28 · 2015 Why this is useful?
  92. 92. MADRID · NOV 27-28 · 2015 Why this is useful? Observables and subscribers can do anything
  93. 93. MADRID · NOV 27-28 · 2015 Why this is useful? Observable a database query Subscriber displaying results on the screen
  94. 94. MADRID · NOV 27-28 · 2015 Why this is useful? Observable a click on the screen Subscriber reacting to it
  95. 95. MADRID · NOV 27-28 · 2015 Why this is useful? Observable a stream of bytes from the internet Subscriber write them to disk
  96. 96. MADRID · NOV 27-28 · 2015 Why this is useful? Observable and Subscriber are independent of the transformations
  97. 97. MADRID · NOV 27-28 · 2015 Why this is useful? I can compose/chain any map/filter calls I want Only matters the return type
  98. 98. MADRID · NOV 27-28 · 2015 Side effects?
  99. 99. MADRID · NOV 27-28 · 2015 Side effects doOn methods: ● doOnNext() for debugging ● doOnError() for error handling ● doOnNext() to save/cache results
  100. 100. MADRID · NOV 27-28 · 2015 Side effects Observable someObservable = Observable .from(Arrays.asList(new Integer[]{2, 7, 11})) .doOnNext(System.out::println) .filter(prime -> prime % 2 == 0) .doOnNext(System.out::println) .count() .doOnNext(System.out::println) .map( number -> String.format(“Contains %d elements”, number) );
  101. 101. MADRID · NOV 27-28 · 2015 Side effects flatMap(id -> service.get() .doOnError(t -> { // report problem to UI }) .onErrorResumeNext(Observable.empty()))
  102. 102. MADRID · NOV 27-28 · 2015 Cold & Hot
  103. 103. MADRID · NOV 27-28 · 2015 Cold & Hot Observables only emit when someone listening? Cold observables only emit when subscribed But hot observables emit instantly
  104. 104. MADRID · NOV 27-28 · 2015 Cold & Hot You can convert between both states ● “Hot -> cold” using defer() or merge(), zip()... ● “Cold -> Hot” using publish() & connect()
  105. 105. MADRID · NOV 27-28 · 2015 Cold & Hot publish & connect? “like transactions” Assume everything is cold
  106. 106. MADRID · NOV 27-28 · 2015 Testing?
  107. 107. MADRID · NOV 27-28 · 2015 More cool things? ● testscheduler ● toIterator() ● Obs.error(), Obs.empty()
  108. 108. MADRID · NOV 27-28 · 2015 Subjects
  109. 109. MADRID · NOV 27-28 · 2015 Subjects Both observable & observer
  110. 110. MADRID · NOV 27-28 · 2015 Subjects AsyncSubject -> takeLast(1) PublishSubject -> publish() ReplaySubject -> replay()/cache() BehaviorSubject -> replay(1)/cache(1)
  111. 111. MADRID · NOV 27-28 · 2015 RxJava in practice Javier Gamarra

×