RxJava est mort, vive RxJava 2 !

7843bb075c05be6886a97b77e36758ff?s=47 David
April 10, 2017

RxJava est mort, vive RxJava 2 !

La migration de RxJava 2 à commencé en 2016. Mais 2017 sera sont année phare et va pouvoir profiter du chemin déjà tracé par sa précédente version.

Quels sont les changements apportés par cette nouvelle version, en terme d’API ou de performances ? En quoi RxJava et RxJava 2 sont-ils différents ? Faut-il migrer sur RxJava 2 tout de suite ?

Cette conférence fera un bref historique des ces bibliothèques avant de répondre à ces différentes questions.

(Android Makers - 10 Avril Paris 2017)

7843bb075c05be6886a97b77e36758ff?s=128

David

April 10, 2017
Tweet

Transcript

  1. RxJava est mort, Vive RxJava 2 !

  2. David Wursteisen

  3. None
  4. Don’t panic !

  5. None
  6. Écrire du code asynchrone : 
 ça craint

  7. Future ExecutorService ex = Executors.newCachedThreadPool();
 Future<String> future = ex.submit(() ->

    longProcessing());
 String result = future.get(); Appel bloquant
  8. Future Future<?> future1 = /* ... */
 Future<?> future2 =

    /* ... */
 Future<?> future3 = /* ... */
 Future<?> future4 = /* ... */
 Future<?> future5 = /* ... */ Orchestration optimale ?
  9. Callback RemoteService service = buildRemoteService();
 service.getUser(id -> {
 service.getData(id, data

    -> {
 service.getSomething(data, whut -> { service.neverEndingCallBack(whut, () -> { }); });
 });
 }); Callback Hell
  10. Relationship Status:
 it’s complicated

  11. Le problème du code synchrone

  12. Synchrone Attente de la réponse Appelant Appelé

  13. Impacte le temps de réponse Serveur lent

  14. Il y a toujours un truc qui ne marche pas

    ça m’énerve !
  15. None
  16. Ça ne marche pas ! ça a planté ? dans

    le doute, reboot
  17. Asynchrone Appelant Appelé Traitement continu

  18. L’asynchrone permet de profiter du temps d’attente

  19. L’asynchrone permet de casser le couplage temporel

  20. Impact minimum sur le temps de réponse

  21. None
  22. Écrire du code asynchrone facilement ?

  23. None
  24. API pour manipuler 
 des événements de manière synchrone ou

    asynchrone à travers un flux d’événements
  25. None
  26. Map ( ⃝ →  ⬛)

  27. None
  28. None
  29. RxView.clicks(btn)
 .doOnNext(evt -> rotation.playFromStart())
 .observeOn(Schedulers.io())
 .switchMap(evt -> remoteApi.getData())
 .observeOn(AndroidSchedulers.mainThread())
 .doOnNext(evt

    -> {
 rotation.stop();
 btn.setRotate(0);
 })
 .doOnNext(value -> btn.setText("Data: " + value))
 .subscribe(); Écoute des clicks Démarrage animation Appel web service Arrêt de l’animation Mise à jour de l’UI Abonnement
  30. None
  31. Grâce à RxJava

  32. Écrire du code asynchrone : 
 ça craint

  33. Il était une fois…

  34. Création des 
 Reactive Extensions Création de RxJava Participation active

    Reprise de 
 RxJava & RxJava 2 Création de Reactor Participation à Reactor
  35. RxJava 
 est une technologie 
 éprouvée

  36. RxJava
 profite des bonnes idées de 
 Reactor (et vice

    versa)
  37. Émergence 
 de différentes approches

  38. 2 Reactive Streams

  39. Reactive Streams API Reactive Streams RxJava 2 Reactor Interface Implémentation

  40. L’API Reactive Streams est 
 un pont 
 entre les

    implémentations
  41. RxJava 2 est une implémentation de Reactive Streams

  42. RxJava n’est pas compatible 
 avec Reactive Streams (il faut

    alors utiliser un adapteur : RxJavaReactiveStreams) https://github.com/ReactiveX/RxJavaReactiveStreams
  43. onNext * ( onError | onComplete ) 
 onNext *

    ( onError | onCompleted ) RxJava Reactive Streams
  44. onNext * ( onError | onComplete ) 
 onNext *

    ( onError | onCompleted ) RxJava Reactive Streams Nom différent
  45. On en reparlera plus tard

  46. Types d’objet

  47. Observable

  48. None
  49. None
  50. None
  51. None
  52. None
  53. Single

  54. None
  55. Completable

  56. None
  57. RxJava Contrat Backpressure Observable [N] Oui Single [1] Non Completable

    [0] Non Ajouté après coup Appel Web service Processus d’arrière plan
  58. Écouter une websocket, pour c h a q u e

    c o m m a n d e r e ç u e , composer une réponse à partir de 3 webservices différents, puis exécuter 2 jobs séquentiellement ?
  59. Écouter une websocket, pour c h a q u e

    c o m m a n d e r e ç u e , composer une réponse à partir de 3 webservices différents, puis exécuter 2 jobs séquentiellement ?
  60. Écouter une websocket, pour c h a q u e

    c o m m a n d e r e ç u e , composer une réponse à partir de 3 webservices différents, puis exécuter 2 jobs séquentiellement ?
  61. Écouter une websocket, pour c h a q u e

    c o m m a n d e r e ç u e , composer une réponse à partir de 3 webservices différents, puis exécuter 2 jobs séquentiellement ?
  62. websocket("/topics/cmd")
 .observeOn(Schedulers.io())
 .switchMap(cmd ->
 Single.zip(
 api.getActions(),
 api.getScore(),
 api.getUserData(),
 this::composeResult).toObservable())
 .observeOn(Schedulers.computation())


    .concatMap(result -> updateDb(result).andThen(getLastResults()))
 .subscribe(last -> System.out.println("last results -> " + last));
  63. websocket("/topics/cmd")
 .observeOn(Schedulers.io())
 .switchMap(cmd ->
 Single.zip(
 api.getActions(),
 api.getScore(),
 api.getUserData(),
 this::composeResult).toObservable())
 .observeOn(Schedulers.computation())


    .concatMap(result -> updateDb(result).andThen(getLastResults()))
 .subscribe(last -> System.out.println("last results -> " + last)); Écoute de la websocket Observable
  64. websocket("/topics/cmd")
 .observeOn(Schedulers.io())
 .switchMap(cmd ->
 Single.zip(
 api.getActions(),
 api.getScore(),
 api.getUserData(),
 this::composeResult).toObservable())
 .observeOn(Schedulers.computation())


    .concatMap(result -> updateDb(result).andThen(getLastResults()))
 .subscribe(last -> System.out.println("last results -> " + last)); Composition d’une réponse à partir de 3 webservices Single
  65. websocket("/topics/cmd")
 .observeOn(Schedulers.io())
 .switchMap(cmd ->
 Single.zip(
 api.getActions(),
 api.getScore(),
 api.getUserData(),
 this::composeResult).toObservable())
 .observeOn(Schedulers.computation())


    .concatMap(result -> updateDb(result).andThen(getLastResults()))
 .subscribe(last -> System.out.println("last results -> " + last)); Completable Exécuter 2 jobs
  66. websocket("/topics/cmd")
 .observeOn(Schedulers.io())
 .switchMap(cmd ->
 Single.zip(
 api.getActions(),
 api.getScore(),
 api.getUserData(),
 this::composeResult).toObservable())
 .observeOn(Schedulers.computation())


    .concatMap(result -> updateDb(result).andThen(getLastResults()))
 .subscribe(last -> System.out.println("last results -> " + last)); Écoute de la websocket Observable Composition d’une réponse à partir de 3 webservices Single Completable Exécuter 2 jobs
  67. RxJava 2 Contrat Backpressure Observable [N] Non Single [1] Non

    Completable [0] Non Maybe [0|1] Non Nouveau ! Concept « similaire » à Optional
  68. Maybe

  69. None
  70. Backpressure avec RxJava 2

  71. Consommateur

  72. Consommateur ça déborde !

  73. backpressure

  74. MissingBackpressureException ?

  75. acceptedIntent
 .filter(intent -> !intent.getBooleanExtra("UpdatePhoneMode", false))
 .concatMap(intent -> approximatedEngine.detectCurrentPlace())
 .doOnNext(score ->

    Log.info(TAG, "Scan completed with result " + score))
 .concatMap(this::detectSleepMode)
 .concatMap((score) -> isNewPlace(score.getScore().getPlace()).map(p -> score))
 .doOnNext((p) -> Log.info(TAG, "Current place found is : " + p))
 .subscribe()
  76. acceptedIntent
 .filter(intent -> !intent.getBooleanExtra("UpdatePhoneMode", false)) .onBackpressureDrop()
 .concatMap(intent -> approximatedEngine.detectCurrentPlace())
 .doOnNext(score

    -> Log.info(TAG, "Scan completed with result " + score))
 .onBackpressureDrop() .concatMap(this::detectSleepMode)
 .onBackpressureDrop()
 .concatMap((score) -> isNewPlace(score.getScore().getPlace()).map(p -> score))
 .doOnNext((p) -> Log.info(TAG, "Current place found is : " + p))
 .subscribe() Ajouté dans un moment de panique
  77. RxJava 2 Contrat Backpressure Observable [N] Non Single [1] Non

    Completable [0] Non Maybe [0|1] Non Nouveau ! Concept « similaire » à Optional
  78. RxJava 2 Contrat Backpressure Observable [N] Non Single [1] Non

    Completable [0] Non Maybe [0|1] Non Flowable [N] Oui Nouveau ! Observable avec 
 back pressure Concept « similaire » à Optional
  79. Observable → moins de 1000 éléments → Gestion d’élément d’interface

    graphique → Remplacement de Stream Java Flowable → plus de 10 000 éléments → contrôle de l’émission de données → Flux réseau avec contrôle de débit
  80. Types d’objets et
 Reactive Streams

  81. Publisher Flux Flowable Reactive Streams

  82. Flux.range(1, 10)
 .flatMap(i -> Flux.just(1))
 .subscribe();

  83. Flux.range(1, 10)
 .flatMap(i -> Flux.just(1))
 .subscribe(); Publisher

  84. Flux.range(1, 10)
 .flatMap(i -> Flowable.just(1))
 .subscribe(); Publisher RxJava 2

  85. Flowable.defer(() -> Flux.range(1, 10))
 .subscribe(System.out::println); RxJava 2 Reactor

  86. Flux.defer(() -> Flowable.range(1, 10))
 .subscribe(System.out::println); RxJava 2 Reactor

  87. P o u v o i r u t i

    l i s e r u n e biblio t hèq ue utilisant Reactive Streams dans son projet RxJava 2 (et vice versa)
  88. Opérateurs

  89. Catalogue conséquent et homogène

  90. all amb ambArray ambWith any as awaitOnSubscribe blockFirst blockFirstMillis blockLast

    blockLastMillis blockingFirst blockingForEach blockingIterable blockingLast blockingLatest blockingMostRecent blockingNext blockingSingle blockingSubscribe buffer bufferMillis bufferSize bufferTimeout bufferTimeoutMillis bufferUntil bufferWhile cache cacheWithInitialCapacity cancelOn cast checkpoint collect collectInto collectList collectMap collectMultimap collectSortedList combineLatest combineLatestDelayError compose concat concatArray concatArrayDelayError concatArrayEager concatDelayError concatEager concatMap concatMapDelayError concatMapEager concatMapEagerDelayError concatMapIterable concatWith contains count create debounce defaultIfEmpty defer delay delayElements delayElementsMillis delayMillis delaySubscription delaySubscriptionMillis dematerialize distinct distinctUntilChanged doAfterNext doAfterTerminate doFinally doOnCancel doOnComplete doOnEach doOnError doOnLifecycle doOnNext doOnRequest doOnSubscribe doOnTerminate elapsed elementAt elementAtOrError empty equals error filter first firstElement firstEmitting firstEmittingWith firstOrError flatMap flatMapCompletable flatMapIterable flatMapMaybe flatMapSequential flatMapSingle forEach forEachWhile from fromArray fromCallable fromFuture fromIterable fromPublisher fromStream generate getClass getPrefetch groupBy groupJoin handle hasElement hasElements hashCode hide ignoreElements interval intervalMillis intervalRange isEmpty join just last lastElement lastOrError lift limitRate log map mapError materialize merge mergeArray mergeArrayDelayError mergeDelayError mergeSequential mergeWith never next notify notifyAll observeOn ofType onBackpressureBuffer onBackpressureDrop onBackpressureError onBackpressureLatest onErrorResumeNext onErrorResumeWith onErrorReturn onErrorReturnItem onExceptionResumeNext onTerminateDetach parallel publish publishNext publishOn range rangeLong rebatchRequests reduce reduceWith repeat repeatUntil repeatWhen replay replayMillis retry retryUntil retryWhen safeSubscribe sample sampleFirst sampleFirstMillis sampleMillis sampleTimeout scan scanWith sequenceEqual serialize share single singleElement singleOrEmpty singleOrError skip skipLast skipMillis skipUntil skipUntilOther skipWhile sort sorted startWith startWithArray strict subscribe subscribeOn subscribeWith switchIfEmpty switchMap switchMapDelayError switchOnError switchOnNext switchOnNextDelayError take takeLast takeMillis takeUntil takeUntilOther takeWhile test then thenEmpty thenMany throttleFirst throttleLast throttleWithTimeout timeInterval timeout timeoutMillis timer timestamp to toFuture toIterable toList toMap toMultimap toObservable toSortedList toStream toString transform unsafeCreate unsubscribeOn using wait window windowMillis windowTimeout windowTimeoutMillis windowUntil windowWhile withLatestFrom zip zipArray zipIterable zipWith zipWithIterable
  91. RxJava RxJava 2 flatMap flatMap Émission d’aucune, une ou plusieurs

    valeurs amb amb Émission des valeurs du flux répondant en premier … … … debounce debounce Ignore les événements pendant un laps de temps
  92. RxJava RxJava 2 Observable.fromAsync Observable.create Observable<T> first() Maybe<T> firstElement() Observable<T>

    firstOrDefault(T) Single<T> first(T) Observable<T> ignoreElements() Completable ignoreElements()
  93. RxJava RxJava 2 Observable.fromAsync Observable.create Observable<T> first() Maybe<T> firstElement() Observable<T>

    firstOrDefault(T) Single<T> first(T) Observable<T> ignoreElements() Completable ignoreElements()
  94. RxJava RxJava 2 Observable.fromAsync Observable.create Observable<T> first() Maybe<T> firstElement() Observable<T>

    firstOrDefault(T) Single<T> first(T) Observable<T> ignoreElements() Completable ignoreElements()
  95. RxJava RxJava 2 Observable.fromAsync Observable.create Observable<T> first() Maybe<T> firstElement() Observable<T>

    firstOrDefault(T) Single<T> first(T) Observable<T> ignoreElements() Completable ignoreElements()
  96. RxJava RxJava 2 Observable.fromAsync Observable.create Observable<T> first() Maybe<T> firstElement() Observable<T>

    firstOrDefault(T) Single<T> first(T) Observable<T> ignoreElements() Completable ignoreElements()
  97. L’ensemble des opérateurs couvre de nombreuses situations

  98. Nota bene

  99. https://github.com/ReactiveX/RxJava/wiki/Implementing-custom-operators-(draft) writing operators is hard when one writes an operator,

    the Observable protocol, unsubscription, backpressure and concurrency have to be taken into account and adhered to the letter
  100. Écrire un opérateur avec RxJava 2 est plus complexe qu’avec

    RxJava
  101. Asynchrone gestion de contexte d’exécution

  102. Schedulers Rethink cette partie là

  103. Scheduler 
 (Pool de Thread) Tâche 1 Tâche 2 Tâche

    3 Tâche 4
  104. Tâche 1 Tâche 2 Tâche 3 Tâche 4 Scheduler 


    (Pool de Thread)
  105. Tâche 1 Tâche 2 Tâche 3 Tâche 4 Scheduler 


    (Pool de Thread)
  106. Tâche 1 Tâche 2 Tâche 3 Tâche 4 Scheduler 


    (Pool de Thread)
  107. Tâche 1 Tâche 2 Tâche 3 Tâche 4 Scheduler 


    (Pool de Thread)
  108. Tâche 1 Tâche 2 Tâche 3 Tâche 4 Scheduler 


    (Pool de Thread)
  109. Tâche 1 Tâche 2 Tâche 3 Tâche 4 Scheduler 


    (Pool de Thread)
  110. Tâche 1 Tâche 2 Tâche 3 Tâche 4 Scheduler 


    (Pool de Thread)
  111. Tâche 1 Tâche 2 Tâche 3 Tâche 4 Scheduler 


    (Pool de Thread)
  112. Scheduler 
 (Single Thread) Tâche 1 Tâche 2 Tâche 3

    Tâche 4
  113. Scheduler 
 (Single Thread) Tâche 1 Tâche 2 Tâche 3

    Tâche 4
  114. Scheduler 
 (Single Thread) Tâche 1 Tâche 2 Tâche 3

    Tâche 4
  115. Scheduler 
 (Single Thread) Tâche 1 Tâche 2 Tâche 3

    Tâche 4
  116. Scheduler 
 (Single Thread) Tâche 1 Tâche 2 Tâche 3

    Tâche 4
  117. Scheduler 
 (Single Thread) Tâche 1 Tâche 2 Tâche 3

    Tâche 4
  118. Scheduler 
 (Single Thread) Tâche 1 Tâche 2 Tâche 3

    Tâche 4
  119. Scheduler 
 (Single Thread) Tâche 1 Tâche 2 Tâche 3

    Tâche 4
  120. Scheduler 
 (Single Thread) Tâche 1 Tâche 2 Tâche 3

    Tâche 4
  121. java.lang.IllegalStateException: 
 Not on the main thread NetworkOnMainThreadException

  122. RxView.clicks(btn) 
 .observeOn(Schedulers.io())
 .switchMap(evt -> remoteApi.getData())
 .observeOn(Schedulers.computation())
 .flatMap(data -> intensiveComputation(data))


    .observeOn(AndroidSchedulers.mainThread())
 .doOnNext(value -> btn.setText("Data: " + value)) 
 .subscribe();
  123. RxView.clicks(btn) 
 .observeOn(Schedulers.io())
 .switchMap(evt -> remoteApi.getData())
 .observeOn(Schedulers.computation())
 .flatMap(data -> intensiveComputation(data))


    .observeOn(AndroidSchedulers.mainThread())
 .doOnNext(value -> btn.setText("Data: " + value)) 
 .subscribe(); entrée/sortie calculs Thread graphique
  124. RxJava RxJava 2 Description io() io() Pool de Thread qui

    grossit au besoin computation() computation() Pool fini de Thread single() single() Pool de 1 Thread immediate() Execute la tâche immédiatement trampoline() trampoline() Ajoute la tâche dans une file d’attente avant de l’executer
  125. RxJava RxJava 2 Description io() io() Pool de Thread qui

    grossit au besoin computation() computation() Pool fini de Thread single() single() Pool de 1 Thread immediate() Execute la tâche immédiatement trampoline() trampoline() Ajoute la tâche dans une file d’attente avant de l’executer
  126. RxJava RxJava 2 Description io() io() Pool de Thread qui

    grossit au besoin computation() computation() Pool fini de Thread single() single() Pool de 1 Thread immediate() Execute la tâche immédiatement trampoline() trampoline() Ajoute la tâche dans une file d’attente avant de l’executer
  127. RxJava RxJava 2 Description io() io() Pool de Thread qui

    grossit au besoin computation() computation() Pool fini de Thread single() single() Pool de 1 Thread immediate() Execute la tâche immédiatement trampoline() trampoline() Ajoute la tâche dans une file d’attente avant de l’executer
  128. RxJava RxJava 2 Description io() io() Pool de Thread qui

    grossit au besoin computation() computation() Pool fini de Thread single() single() Pool de 1 Thread immediate() Execute la tâche immédiatement trampoline() trampoline() Ajoute la tâche dans une file d’attente avant de l’executer Absent pour votre bien
  129. RxJava RxJava 2 Description io() io() Pool de Thread qui

    grossit au besoin computation() computation() Pool fini de Thread single() single() Pool de 1 Thread immediate() Execute la tâche immédiatement trampoline() trampoline() Ajoute la tâche dans une file d’attente avant de l’executer
  130. Backpressure

  131. Consommateur ça déborde !

  132. Flowable.range(1, 100000)
 .subscribe(new Subscriber<Integer>() {
 
 private Subscription source;
 


    @Override
 public void onSubscribe(Subscription s) {
 this.source = s;
 this.source.request(1);
 }
 
 @Override
 public void onNext(Integer o) {
 longComputation(o);
 this.source.request(1);
 }
 });
  133. Flowable.range(1, 100000)
 .subscribe(new Subscriber<Integer>() {
 
 private Subscription source;
 


    @Override
 public void onSubscribe(Subscription s) {
 this.source = s;
 this.source.request(1);
 }
 
 @Override
 public void onNext(Integer o) {
 longComputation(o);
 this.source.request(1);
 }
 }); Garder la référence de l’abonnement Demander l’émission des éléments suivants Demande l’émission des premiers éléments
  134. Flowable.range(1, 100000)
 .subscribe(new Subscriber<Integer>() {
 
 private Subscription source;
 


    @Override
 public void onSubscribe(Subscription s) {
 this.source = s;
 this.source.request(1);
 }
 
 @Override
 public void onNext(Integer o) {
 longComputation(o);
 this.source.request(1);
 }
 }); Reactive Streams
  135. Flowable.range(1, 100000)
 .subscribe(new Subscriber<Integer>() {
 
 private Subscription source;
 


    @Override
 public void onSubscribe(Subscription s) {
 this.source = s;
 this.source.request(1);
 }
 
 @Override
 public void onNext(Integer o) {
 longComputation(o);
 this.source.request(1);
 }
 }); Contrôle de l’émission
  136. source()
 .subscribe(new Subscriber<Integer>() {
 
 private Subscription source;
 
 @Override


    public void onSubscribe(Subscription s) {
 this.source = s;
 this.source.request(1);
 }
 
 @Override
 public void onNext(Integer o) {
 longComputation(o);
 this.source.request(1);
 }
 }); Update GPS Liste déroulante
  137. Rendre son application Reactive

  138. -Jake Wharton « Unless you can model your entire system

    synchronously, a single asynchronous source breaks imperative programming »
  139. -Jake Wharton « Unless you can model your entire system

    synchronously, a single asynchronous source breaks imperative programming »
  140. Reactive Reactive API Synchrone Callback Reactive Reactive

  141. Utilisation de Factory

  142. RxJava
 RxJava 2 Flowable.just Émission d’une valeur existante Flowable.defer Émission

    tardive d’un Observable Flowable.fromCallable Émission à partir d’un appel de fonction Flowable.create Contrôle manuel de l’émission des événements Flowable.using Gestion d’une ressource Flowable.fromPublisher Utilisation d’un Publisher (Reactive Streams) Flowable.generate Utilisation d’un générateur de valeurs
  143. RxJava
 RxJava 2 Flowable.just Émission d’une valeur existante Flowable.defer Émission

    tardive d’un Observable Flowable.fromCallable Émission à partir d’un appel de fonction Flowable.create Contrôle manuel de l’émission des événements Flowable.using Gestion d’une ressource Flowable.fromPublisher Utilisation d’un Publisher (Reactive Streams) Flowable.generate Utilisation d’un générateur de valeurs
  144. RxJava
 RxJava 2 Flowable.just Émission d’une valeur existante Flowable.defer Émission

    tardive d’un Observable Flowable.fromCallable Émission à partir d’un appel de fonction Flowable.create Contrôle manuel de l’émission des événements Flowable.using Gestion d’une ressource Flowable.fromPublisher Utilisation d’un Publisher (Reactive Streams) Flowable.generate Utilisation d’un générateur de valeurs
  145. RxJava
 RxJava 2 Flowable.just Émission d’une valeur existante Flowable.defer Émission

    tardive d’un Observable Flowable.fromCallable Émission à partir d’un appel de fonction Flowable.create Contrôle manuel de l’émission des événements Flowable.using Gestion d’une ressource Flowable.fromPublisher Utilisation d’un Publisher (Reactive Streams) Flowable.generate Utilisation d’un générateur de valeurs
  146. Flowable.fromCallable(() -> computeValue())
 .subscribe(System.out::println);

  147. Flowable.fromCallable(() -> computeValue())
 .subscribe(System.out::println); Création d’une valeur tardive

  148. RxJava
 RxJava 2 Flowable.just Émission d’une valeur existante Flowable.defer Émission

    tardive d’un Observable Flowable.fromCallable Émission à partir d’un appel de fonction Flowable.create Contrôle manuel de l’émission des événements Flowable.using Gestion d’une ressource Flowable.fromPublisher Utilisation d’un Publisher (Reactive Streams) Flowable.generate Utilisation d’un générateur de valeurs
  149. Observable.<Event>create(emitter -> {
 Callback listener = new Callback() {
 @Override


    public void onEvent(Event e) {
 emitter.onNext(e);
 if (e.isLast()) {
 emitter.onComplete();
 }
 }
 
 @Override
 public void onFailure(Exception e) {
 emitter.onError(e);
 }
 };
 
 AutoCloseable c = api.someMethod(listener);
 
 emitter.setCancellation(c::close);
 
 }); Contract RxJava Contract RxJava Désabonnement
  150. Flowable.<Event>create(emitter -> {
 Callback listener = new Callback() {
 @Override


    public void onEvent(Event e) {
 emitter.onNext(e);
 if (e.isLast()) {
 emitter.onComplete();
 }
 }
 
 @Override
 public void onFailure(Exception e) {
 emitter.onError(e);
 }
 };
 
 AutoCloseable c = api.someMethod(listener);
 
 emitter.setCancellation(c::close);
 
 }, BackpressureStrategy.BUFFER); Backpressure
  151. Migrer son application RxJava

  152. Reactive Streams n’ acceptent pas de valeur null (sauf Maybe.fromCallable)

  153. Observable.<Void>fromCallable(() -> {
 voidMethod();
 return null;
 }).subscribe(); RxJava Contrainte technique

    de compilation
  154. RxJava 2 Observable.just(null);
 
 Single.just(null);
 
 Observable.fromCallable(() -> null)
 .subscribe(System.out::println,

    Throwable::printStackTrace);
 
 Observable.just(1).map(v -> null)
 .subscribe(System.out::println, Throwable::printStackTrace); NullPointerException NullPointerException NullPointerException N ullPointerException
  155. Observable.range(1, 10)
 .map(i -> {
 if (i % 2 ==

    0) {
 return null;
 } else {
 return i;
 }
 })
 .filter(i -> i != null)
 .subscribe(System.out::println); émission de null filtre de null RxJava
  156. Observable.range(1, 10)
 .flatMap(i -> {
 if (i % 2 ==

    0) {
 return Observable.empty();
 } else {
 return Observable.just(i);
 }
 })
 .subscribe(System.out::println); émission de empty RxJava 2
  157. Disposable abonnement = observeClicks()
 .map(evt -> "click !")
 .subscribe();
 


    CompositeDisposable abonnements = new CompositeDisposable(abonnement);
 
 abonnements.clear(); Subscription → Disposable CompositeSubscription → CompositeDisposable
  158. Est-ce que ça va faire mal ?

  159. rx.Observable io.reactivex.Observable rx.Single rx.Completable io.reactivex.Completable io.reactivex.Single RxJava RxJava 2 package

    différent
  160. rx.Action1 rx.Func1 RxJava RxJava 2 rx.Func2 rx.Func3 rx.Action2 io.reactivex.functions.Consumer io.reactivex.functions.Function

    io.reactivex.functions.BiFunction io.reactivex.functions.Function3 io.reactivex.functions.BiConsumer Suivre les conventions Java 8
  161. RxJavaInterop.toV2Observable(rx.Observable.just(1, 2, 3))
 .firstElement()
 .subscribe();
 
 RxJavaInterop.toV1Observable(io.reactivex.Observable.just(1, 2, 3), 


    BackpressureStrategy.DROP)
 .first()
 .subscribe(); https://github.com/akarnokd/RxJava2Interop RxJava → RxJava 2 RxJava 2 → RxJava
  162. Observable.interval(1, TimeUnit.SECONDS)
 .map(i -> String.valueOf(i))
 .subscribe();

  163. Observable.interval(1, TimeUnit.SECONDS)
 .map(i -> String.valueOf(i))
 .subscribe(); java.util.concurrent.TimeUnit

  164. Observable.interval(1, TimeUnit.SECONDS)
 .map(i -> String.valueOf(i))
 .subscribe(); io.reactivex.functions.Function

  165. Gestion des erreurs

  166. public class AndroidApp extends Application {
 
 
 static {


    
 RxJavaPlugins.getInstance().registerErrorHandler(new RxJavaErrorHandler() {
 @Override
 public void handleError(Throwable e) {
 e.printStackTrace();
 Log.error("RX-EXCEPTION", "An Stream throw an exception ", e);
 }
 });
 } } Doit être défini en 1er Gestion d’erreur par défaut
  167. RxJavaPlugins.setErrorHandler(Functions.<Throwable>emptyConsumer()); Peut être défini au runtime Gestion d’erreur par défaut

  168. Debug Rajouter stack insignifiant

  169. rx.exceptions.OnErrorNotImplementedException: Sequence contains too many elements at rx.internal.util.InternalObservableUtils$ErrorNotImplementedAction.call(InternalObservableUtils.java: 386) at

    rx.internal.util.InternalObservableUtils$ErrorNotImplementedAction.call(InternalObservableUtils.java: 383) at rx.internal.util.ActionSubscriber.onError(ActionSubscriber.java:44) at rx.observers.SafeSubscriber._onError(SafeSubscriber.java:153) at rx.observers.SafeSubscriber.onError(SafeSubscriber.java:115) at rx.internal.operators.OperatorSingle$ParentSubscriber.onNext(OperatorSingle.java:97) at rx.internal.operators.OnSubscribeRange$RangeProducer.slowPath(OnSubscribeRange.java:90) at rx.internal.operators.OnSubscribeRange$RangeProducer.request(OnSubscribeRange.java:68) at rx.Subscriber.setProducer(Subscriber.java:211) at rx.internal.operators.OnSubscribeRange.call(OnSubscribeRange.java:38) Stacktrace inexploitable
  170. RxJavaHooks.enableAssemblyTracking(); […] Caused by: rx.exceptions.AssemblyStackTraceException: Assembly trace: at rx.Observable.create(Observable.java:100) at

    rx.Observable.lift(Observable.java:237) at rx.Observable.single(Observable.java:9330) at rxjava2.BasicExampleTest.stacktrace(BasicExampleTest.java:225) rx.Observable.range(1, 100)
 .single()
 .subscribe();
  171. enableTracing n’est pas encore supporté par RxJava 2 (pour cela,

    il faut utiliser RxJava2Extensions) https://github.com/akarnokd/RxJava2Extensions
  172. Attention dégradation des performances !

  173. Performance

  174. Génération 3 4 5+ Fusion RxJava 2 Reactor

  175. Attention Slides conceptuels

  176. Sans fusion

  177. Transform (  ⬛ → ⃝ ) Transform ( ⃝

    →  ⬛)
  178. Transform (  ⬛ → ⃝ ) Transform ( ⃝

    →  ⬛)
  179. Transform (  ⬛ → ⃝ ) Transform ( ⃝

    →  ⬛)
  180. Transform (  ⬛ → ⃝ ) Transform ( ⃝

    →  ⬛)
  181. Transform (  ⬛ → ⃝ ) Transform ( ⃝

    →  ⬛)
  182. Transform (  ⬛ → ⃝ ) Transform ( ⃝

    →  ⬛)
  183. Avec fusion

  184. Transform (  ⬛ → ⃝ ) Transform ( ⃝

    →  ⬛)
  185. Transform (  ⬛ → ⃝ ) Transform ( ⃝

    →  ⬛)
  186. Transform (  ⬛ → ⃝ ) Transform ( ⃝

    →  ⬛)
  187. Transform (  ⬛ → ⃝ ) Transform ( ⃝

    →  ⬛)
  188. Transform (  ⬛ → ⃝ ) Transform ( ⃝

    →  ⬛)
  189. La fusion diminue la consommation mémoire et augmente les performances

  190. for (int x = 0; x < 10_000; x++) {


    
 Observable.interval(10, TimeUnit.MILLISECONDS)
 .takeWhile(i -> take.get())
 .flatMap(i -> Observable.range(1, 100))
 .subscribe();
 }
  191. RxJava 2 RxJava Reactor

  192. http://akarnokd.blogspot.fr/2016/12/the-reactive-scrabble-benchmarks.html Stream Java 8 RxJava 2 / Reactor RxJava Décembre

    2016
  193. Stream Java 8 RxJava 2 / Reactor RxJava https://twitter.com/akarnokd/status/844555409012740096 Mars

    2017
  194. RxJava 2 : 
 streams performants pour Android

  195. Ecosystème

  196. None
  197. None
  198. RxJava RxJava 2 Retrofit Oui Oui RxAndroid Oui Oui Realm

    Oui Non
  199. We are aggressively 
 migrating our internal code to RxJava

    2 https://github.com/uber/AutoDispose
  200. Android RxJava

  201. Android RxJava 2

  202. Merci pour votre attention On reste en contact ? david.wursteisen@gmail.com

    @dwursteisen http://blog.soat.fr RefCard RxJava 2 bientôt disponible !