RxJava - Getting Started

7843bb075c05be6886a97b77e36758ff?s=47 David
October 16, 2014

RxJava - Getting Started

Les applications sont de plus en plus interconnectées. Une architecture type WOA (Web Oriented Archiecture) et l’utilisation des micros-services nécessitent de faire de plus en plus appel à différents services web. Comment composer un résultat à partir de ces différents services, sans avoir à ce soucier de l’ordre dans lequel les serveurs vont répondre ?

RxJava offre une manière élégante de faire de l’asynchrone et de la composition au sein de son application. David vous exposera les concepts de Rx (Reactive eXtension) avant de vous montrer une mise en application avec des exemples de code venant d’une application Android.

David Wursteisen / Soat / 16 Octobre 2014

7843bb075c05be6886a97b77e36758ff?s=128

David

October 16, 2014
Tweet

Transcript

  1. None
  2. Getting Started RxJava David Wursteisen 16 Octobre 2014

  3. David Wursteisen @dwursteisen Direction Expertise Innovation

  4. David Wursteisen

  5. Architecture distribuée Sync/Async/Concurrence

  6. Architecture distribuée

  7. Architecture distribuée

  8. Architecture distribuée The Internet

  9. Architecture distribuée The Internet

  10. Synchrone

  11. Synchrone Appel bloquant

  12. Asynchrone

  13. Asynchrone Appel non bloquant

  14. Complexité

  15. Complexité future.get();

  16. Complexité future1.get(); future2.get(); future3.get(); future4.get(); future5.get(); future6.get(); future7.get();

  17. Complexité future1.get(); future2.get(); future3.get(); future4.get(); future5.get(); future6.get(); future7.get(); Ordonnancement optimal

    ?
  18. Complexité client.execute(new Callback() { @Override public void completed(HttpResponse response) {

    } });
  19. Complexité client.execute(new Callback() { @Override public void completed(HttpResponse response) {

    client.execute(new Callback() { @Override public void completed(HttpResponse response) { } }); } });
  20. Complexité client.execute(new Callback() { @Override public void completed(HttpResponse response) {

    client.execute(new Callback() { @Override public void completed(HttpResponse response) { client.execute(new Callback() { @Override public void completed(HttpResponse response) { } }); } });
  21. Complexité client.execute(new Callback() { @Override public void completed(HttpResponse response) {

    client.execute(new Callback() { @Override public void completed(HttpResponse response) { client.execute(new Callback() { @Override public void completed(HttpResponse response) { } }); } }); Callback hell
  22. Concurrence

  23. Concurrence

  24. Concurrence Concurrence

  25. Concurrence

  26. Concurrence RxJava permet de manipuler des évènements d’une manière synchrone

    et/ou asynchrone.
  27. Historique Il était une fois...

  28. Historique

  29. Historique

  30. Historique

  31. Historique

  32. Historique ReactiveX.io

  33. Observables Travailler avec des flux

  34. Flux d’évènements fini Évènements Fin du flux

  35. Flux d’évènements en erreur Évènements Erreur

  36. Flux d’évènements infini Évènements

  37. Flux d’évènements Observable.never() Observable.empty() Observable.just(1) Observable.from(1, 2, 3) Observable.range(1, 4400)

    Observable.timer(5, TimeUnit.SECONDS) Observable.create(...)
  38. Flux d’évènements Observable.never() Observable.empty() Observable.just(1) Observable.from(1, 2, 3) Observable.range(1, 4400)

    Observable.timer(5, TimeUnit.SECONDS) Observable.create(...)
  39. Flux d’évènements Observable.never() Observable.empty() Observable.just(1) Observable.from(1, 2, 3) Observable.range(1, 4400)

    Observable.timer(5, TimeUnit.SECONDS) Observable.create(...) 1
  40. Flux d’évènements Observable.never() Observable.empty() Observable.just(1) Observable.from(1, 2, 3) Observable.range(1, 4400)

    Observable.timer(5, TimeUnit.SECONDS) Observable.create(...) 1 2 3
  41. Flux d’évènements Observable.never() Observable.empty() Observable.just(1) Observable.from(1, 2, 3) Observable.range(1, 4400)

    Observable.timer(5, TimeUnit.SECONDS) Observable.create(...) 1 4400
  42. Flux d’évènements Observable.never() Observable.empty() Observable.just(1) Observable.from(1, 2, 3) Observable.range(1, 4400)

    Observable.timer(5, TimeUnit.SECONDS) Observable.create(...) 0 t t + 5 secondes
  43. Flux d’évènements Observable.never() Observable.empty() Observable.just(1) Observable.from(1, 2, 3) Observable.range(1, 4400)

    Observable.timer(5, TimeUnit.SECONDS) Observable.create(...) A C
  44. Flux d’évènements λ ϕ φ json json json Observable<json> Observable<Integer>

    Observable<Click>
  45. Observer Push des données

  46. Observer OnNext* (OnCompleted|OnError)?

  47. Observer OnNext* (OnCompleted|OnError)?

  48. Observer OnNext* (OnCompleted|OnError)?

  49. Observer OnNext* (OnCompleted|OnError)?

  50. Observer Observable.range(1, 4400)

  51. Observer Observable.range(1, 4400).subscribe()

  52. Observer Observable.range(1, 4400).subscribe(onNext)

  53. Observer Observable.range(1, 4400).subscribe(System.out::println)

  54. Observer Observable.range(1, 4400).subscribe(System.out::println, onError)

  55. Observer Observable.range(1, 4400).subscribe(System.out::println, System.err::println)

  56. Observer Observable.range(1, 4400).subscribe(System.out::println, System.err::println, onCompleted)

  57. Observer Observable.range(1, 4400).subscribe(System.out::println, System.err::println, () -> System.out.println(“finished”))

  58. Manipulation d’évènements Quand l’écoute ne suffit plus

  59. Manipulation d’évènements 0 1

  60. Manipulation d’évènements 0 1 map

  61. Manipulation d’évènements 0 1 A B map

  62. Manipulation d’évènements 1 4

  63. Manipulation d’évènements 1 4 filter ( x <= 2 )

  64. Manipulation d’évènements 1 4 1 filter ( x <= 2

    )
  65. Manipulation d’évènements 1 2

  66. Manipulation d’évènements 1 2 delay ( 5, SECONDS )

  67. Manipulation d’évènements 1 2 1 delay ( 5, SECONDS )

    2
  68. Manipulation d’évènements Observable.from(0, 1, 2, 3, 4) Observable<Integer>

  69. Manipulation d’évènements Observable.from(0, 1, 2, 3, 4) .filter((i) -> i

    < 3) Observable<Integer> Observable<Integer>
  70. Manipulation d’évènements Observable.from(0, 1, 2, 3, 4) .filter((i) -> i

    < 3) .delay(5, TimeUnit.SECONDS) Observable<Integer> Observable<Integer> Observable<Integer>
  71. Manipulation d’évènements Observable.from(0, 1, 2, 3, 4) .filter((i) -> i

    < 3) .delay(5, TimeUnit.SECONDS) .map((i) -> Character.toString((char)(i + 'A'))) Observable<Integer> Observable<Integer> Observable<Integer> Observable<String>
  72. Manipulation d’évènements Observable.from(0, 1, 2, 3, 4) .filter((i) -> i

    < 3) .delay(5, TimeUnit.SECONDS) .map((i) -> Character.toString((char)(i + 'A'))) .subscribe(System.out::println); Observable<Integer> Observable<Integer> Observable<Integer> Observable<String>
  73. Manipulation d’évènements Observable.from(0, 1, 2, 3, 4) .filter((i) -> i

    < 3) .delay(5, TimeUnit.SECONDS) .map((i) -> Character.toString((char)(i + 'A'))) .subscribe(System.out::println); 0, 1, 2, 3, 4 => A, B, C Observable<Integer> Observable<Integer> Observable<Integer> Observable<String>
  74. Manipulation d’évènements

  75. Manipulation d’évènements

  76. Manipulation d’évènements

  77. Composition Création d’un flux à partir d’un ensemble de flux

  78. Composition

  79. Composition

  80. Composition

  81. Mise en pratique de composition Learn from the trenches

  82. Composition

  83. Composition

  84. Composition

  85. Composition

  86. Composition

  87. Composition merge

  88. Composition merge

  89. Composition

  90. Composition

  91. Composition zip

  92. Composition zip

  93. Subscription Et gestion de l’unsubscribe

  94. Subscription Observable.create(new OnSubscribe<T>() { … });

  95. Subscription Observable.create(new OnSubscribe<T>() { @Override public void call(Subscriber<? super T>

    s) { s.onNext(123); s.onCompleted(); } });
  96. Subscription Observable.create(new OnSubscribe<T>() { @Override public void call(Subscriber<? super T>

    s) { s.onNext(123); s.onCompleted(); } }); Émission synchronne
  97. Subscription Observable.create(new OnSubscribe<T>() { @Override public void call(Subscriber<? super T>

    subscriber) { // ... httpClient.execute(httpRequest, new FutureCallback<HttpResponse>() { @Override public void completed(String content) { subscriber.onNext(content); subscriber.onCompleted(); } @Override public void failed(Exception e) { subscriber.onError(e); } }); } });
  98. Subscription Observable.create(new OnSubscribe<T>() { @Override public void call(Subscriber<? super T>

    subscriber) { // ... httpClient.execute(httpRequest, new FutureCallback<HttpResponse>() { @Override public void completed(String content) { subscriber.onNext(content); subscriber.onCompleted(); } @Override public void failed(Exception e) { subscriber.onError(e); } }); } });
  99. Subscription Observable.create(new OnSubscribe<T>() { @Override public void call(Subscriber<? super T>

    subscriber) { // ... httpClient.execute(httpRequest, new FutureCallback<HttpResponse>() { @Override public void completed(String content) { subscriber.onNext(content); subscriber.onCompleted(); } @Override public void failed(Exception e) { subscriber.onError(e); } }); } });
  100. Subscription Observable.create(new OnSubscribe<T>() { @Override public void call(Subscriber<? super T>

    subscriber) { // ... httpClient.execute(httpRequest, new FutureCallback<HttpResponse>() { @Override public void completed(String content) { subscriber.onNext(content); subscriber.onCompleted(); } @Override public void failed(Exception e) { subscriber.onError(e); } }); } }); Émission asynchronne
  101. Subscription Observable.create(new OnSubscribe<T>() { @Override public void call(Subscriber<? super T>

    subscriber) { // ... httpClient.execute(httpRequest, new FutureCallback<HttpResponse>() { @Override public void completed(String content) { subscriber.onNext(content); subscriber.onCompleted(); } @Override public void failed(Exception e) { subscriber.onError(e); } }); } }); Propagation des erreurs
  102. Subscription La souscription permet d’uniformiser des API différentes par leurs

    natures (Callback, etc...)
  103. Unsubscribe Subscription subscription = Observable.interval(1, TimeUnit.SECONDS).subscribe();

  104. Unsubscribe Subscription subscription = Observable.interval(1, TimeUnit.SECONDS).subscribe(); Souscription

  105. Unsubscribe Subscription subscription = Observable.interval(1, TimeUnit.SECONDS).subscribe(); Handler sur la souscription

  106. Unsubscribe Subscription subscription = Observable.interval(1, TimeUnit.SECONDS).subscribe(); /* ... */ subscription.unsubscribe();

  107. Unsubscribe Subscription subscription = Observable.interval(1, TimeUnit.SECONDS).subscribe(); /* ... */ subscription.unsubscribe();

    Arrêt de la souscription
  108. Schedulers

  109. Schedulers observableReadingSynchronously(“strings.txt”) .take(10) .delay(1, SECONDS) .map(parse()) .map(n -> “=> ”

    + n)) .subscribe(to_the_view())
  110. Schedulers main

  111. Schedulers observableReadingSynchronously(“strings.txt”) .take(10) .delay(1, SECONDS) .map(parse()) .map(n -> “=> ”

    + n)) .subscribe(to_the_view())
  112. Schedulers Computation IO UI main

  113. Schedulers Computation IO UI main

  114. Schedulers Computation IO UI main

  115. Schedulers Computation IO UI main

  116. Schedulers Computation IO UI main

  117. Schedulers Computation IO UI main

  118. Schedulers observableReadingSynchronously(“strings.txt”) .subscribeOn(scheduler) .take(10) .delay(1, SECONDS, scheduler) .map(parse()) .observeOn(scheduler) .map(n

    -> “=> ” + n)) .subscribe(to_the_view())
  119. Schedulers observableReadingSynchronously(“strings.txt”) .subscribeOn(Schedulers.io()) .take(10) .delay(1, SECONDS, Schedulers.computation()) .map(parse()) .observeOn(Schedulers.from(uiExecutor())) .map(n

    -> “=> ” + n)) .subscribe(to_the_view())
  120. Schedulers UI Computation

  121. Schedulers UI Computation

  122. Schedulers UI Computation

  123. Schedulers UI Computation

  124. Schedulers UI Computation

  125. Hot & Cold Observable

  126. Cold Observable Observable<Integer> obs = Observable.from(1, 2, 3, 4); obs.subscribe(System.out::println);

    obs.subscribe(System.out::println);
  127. Cold Observable Observable<Integer> obs = Observable.from(1, 2, 3, 4); obs.subscribe(System.out::println);

    obs.subscribe(System.out::println);
  128. Cold Observable Observable<Integer> obs = Observable.from(1, 2, 3, 4); obs.subscribe(System.out::println);

    obs.subscribe(System.out::println); Subscribe
  129. Cold Observable Observable<Integer> obs = Observable.from(1, 2, 3, 4); obs.subscribe(System.out::println);

    obs.subscribe(System.out::println); Subscribe
  130. Cold Observable Observable<Integer> obs = Observable.from(1, 2, 3, 4); obs.subscribe(System.out::println);

    obs.subscribe(System.out::println); Souscription différente
  131. Hot Observable ConnectableObservable<Integer> obs = Observable.from(1, 2, 3, 4).publish(); obs.subscribe(System.out::println);

    obs.subscribe(System.out::println); obs.connect();
  132. Hot Observable ConnectableObservable<Integer> obs = Observable.from(1, 2, 3, 4).publish(); obs.subscribe(System.out::println);

    obs.subscribe(System.out::println); obs.connect();
  133. Hot Observable ConnectableObservable<Integer> obs = Observable.from(1, 2, 3, 4).publish(); obs.subscribe(System.out::println);

    obs.subscribe(System.out::println); obs.connect();
  134. Hot Observable ConnectableObservable<Integer> obs = Observable.from(1, 2, 3, 4).publish(); obs.subscribe(System.out::println);

    obs.subscribe(System.out::println); obs.connect();
  135. Hot Observable ConnectableObservable<Integer> obs = Observable.from(1, 2, 3, 4).publish(); obs.subscribe(System.out::println);

    obs.subscribe(System.out::println); obs.connect();
  136. Hot Observable ConnectableObservable<Integer> obs = Observable.from(1, 2, 3, 4).publish(); obs.subscribe(System.out::println);

    obs.subscribe(System.out::println); obs.connect(); Subscribe
  137. Hot Observable ConnectableObservable<Integer> obs = Observable.from(1, 2, 3, 4).publish(); obs.subscribe(System.out::println);

    obs.subscribe(System.out::println); obs.connect(); Partage la même souscription
  138. Hot Observable ConnectableObservable<Integer> obs = Observable.from(1, 2, 3, 4).publish(); obs.subscribe(System.out::println);

    obs.subscribe(System.out::println); obs.connect();
  139. Hot Observable ConnectableObservable<Integer> obs = Observable.from(1, 2, 3, 4).publish(); obs.connect();

    obs.subscribe(System.out::println); obs.subscribe(System.out::println); Souscription
  140. Cold & Hot Observable Cold Observable = flux passif Hot

    Observable = flux actif
  141. Back Pressure Contrôler la production

  142. Back Pressure Production

  143. Back Pressure Production buffer

  144. Back Pressure Production Pression arrière

  145. Back Pressure Production Pression arrière Demande de production de n

    élements
  146. Retour d’expérience

  147. Opérateurs Observable.from(1, 2, 3, 4) .reduce(new LinkedList<Integer>(), (seed, value) ->

    { seed.add(value); return seed; }) .first() .subscribe(System.out::println);
  148. Opérateurs Observable.from(1, 2, 3, 4) .reduce(new LinkedList<Integer>(), (seed, value) ->

    { seed.add(value); return seed; }) .first() .subscribe(System.out::println);
  149. Opérateurs Observable.from(1, 2, 3, 4) .toList() .first() .subscribe(System.out::println);

  150. Opérateurs Observable.from(1, 2, 3, 4) .toList() .first() .subscribe(System.out::println);

  151. Opérateurs Observable.from(1, 2, 3, 4) .toList() .first() .subscribe(System.out::println); Différence entre

    first() / single() / take(1) ?
  152. Gestion des erreurs Observable.from(1, 2, 3, 4) .toList() .single() .subscribe(System.out::println);

  153. Gestion des erreurs Observable.from(1, 2, 3, 4) .toList() .single() .subscribe(System.out::println);

    Notification des erreurs absentes
  154. Gestion des erreurs static { RxJavaPlugins.getInstance().registerErrorHandler(new RxJavaErrorHandler() { @Override public

    void handleError(Throwable e) { e.printStackTrace(); } }); }
  155. Lambda & Java 8 Observable.from(1, 2, 3, 4) .filter(new Func1<Integer,

    Boolean>() { @Override public Boolean call(Integer i) { return i > 3; } }) .subscribe(new Action1<Integer>() { @Override public void call(Integer x) { System.out.println(x); } });
  156. Lambda & Java 8 Observable.from(1, 2, 3, 4) .filter(new Func1<Integer,

    Boolean>() { @Override public Boolean call(Integer i) { return i > 3; } }) .subscribe(new Action1<Integer>() { @Override public void call(Integer x) { System.out.println(x); } }); Bruit
  157. Lambda & Java 8 Observable.from(1, 2, 3, 4) .filter(i ->

    i > 3) .subscribe(System.out::println);
  158. Lambda & Java 8 Observable.from(1, 2, 3, 4) .filter(new Func1<Integer,

    Boolean>() { @Override public Boolean call(Integer i) { return i > 3; } }) .subscribe(new Action1<Integer>() { @Override public void call(Integer x) { System.out.println(x); } }); Observable.from(1, 2, 3, 4) .filter(i -> i > 3) .subscribe(System.out::println); Retrolambda
  159. Concurrence obs1.mergeWith(obs2) .take(5) .subscribe(System.out::println);

  160. Concurrence obs1.mergeWith(obs2) .take(5) .subscribe(System.out::println);

  161. Concurrence obs1.mergeWith(obs2) .take(5) .subscribe(System.out::println); Doit gérer la concurrence

  162. Concurrence obs1.mergeWith(obs2) .take(5) .subscribe(System.out::println);

  163. Concurrence obs1.mergeWith(obs2) .take(5) .subscribe(System.out::println); non concurrence

  164. Sync & Async Observable<Integer> generator();

  165. Sync & Async Observable<Integer> generator(); Sync ?

  166. Sync & Async Observable<Integer> generator(); Sync ? Async ?

  167. Sync & Async Observable<Integer> generator(); Sync ? Async ? Computation

    ?
  168. Sync & Async Observable<Integer> generator(); Sync ? Async ? Computation

    ? Acteur ?
  169. “Leak” des Observables everything is an event

  170. “Leak” des Observables ViewPager

  171. “Leak” des Observables ViewPager Preferences Observable

  172. “Leak” des Observables ViewPager Preferences UserService Observable Observable

  173. Future<RxJava>

  174. Future<RxJava> Support RxJava

  175. Reactive Streams

  176. Reactive Streams Reactive Streams is an initiative to provide a

    standard for asynchronous stream processing with non-blocking back pressure on the JVM. http://www.reactive-streams.org/
  177. Reactive Streams RxJava | Akka Streams | Reactor Composable |

    Ratpack
  178. Reactive Streams RxJava | Akka Streams | Reactor Composable |

    Ratpack > 700 Ko | Java | Android
  179. Reactive Streams RxJava | Akka Streams | Reactor Composable |

    Ratpack > 2.5 Mo | Scala | Akka
  180. Reactive Streams RxJava | Akka Streams | Reactor Composable |

    Ratpack ~1Mo | Java | RingBufferDispatcher
  181. Reactive Streams RxJava | Akka Streams | Reactor Composable |

    Ratpack Java 8 | Http
  182. Si il ne fallait retenir qu’une chose

  183. Si il ne fallait retenir qu’une chose RxJava est un

    modèle de programmation pour écrire des applications asynchrones Frontend | Backend | Crossplatform
  184. Questions ? david.wursteisen@soat.fr @dwursteisen