rxjava, getting started - david wursteisen - 16 octobre 2014
Post on 31-May-2015
962 Views
Preview:
DESCRIPTION
TRANSCRIPT
Getting Started
RxJava
David Wursteisen 16 Octobre 2014
David Wursteisen
@dwursteisen
Direction Expertise Innovation
David Wursteisen
Architecture distribuée
Sync/Async/Concurrence
Architecture distribuée
Architecture distribuée
Architecture distribuée
The Internet
Architecture distribuée
The Internet
Synchrone
Synchrone
Appel bloquant
Asynchrone
Asynchrone
Appel non bloquant
Complexité
Complexité
future.get();
Complexité
future1.get();future2.get();future3.get();future4.get();future5.get();future6.get();future7.get();
Complexité
future1.get();future2.get();future3.get();future4.get();future5.get();future6.get();future7.get();
Ordonnancement optimal ?
Complexité
client.execute(new Callback() { @Override public void completed(HttpResponse response) { }});
Complexité
client.execute(new Callback() { @Override public void completed(HttpResponse response) { client.execute(new Callback() { @Override public void completed(HttpResponse response) { } });
}});
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) { } }); }});
}});
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
Concurrence
Concurrence
Concurrence
Concurrence
Concurrence
Concurrence
RxJava permet de manipuler des évènements d’une manière synchrone et/ou asynchrone.
Historique
Il était une fois...
Historique
Historique
Historique
Historique
Historique
ReactiveX.io
Observables
Travailler avec des flux
Flux d’évènements fini
Évènements Fin du flux
Flux d’évènements en erreur
Évènements Erreur
Flux d’évènements infini
Évènements
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(...)
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(...)
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
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
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
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
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
Flux d’évènements
λ ϕ φ
json json jsonObservable<json>
Observable<Integer>
Observable<Click>
Observer
Push des données
Observer
OnNext* (OnCompleted|OnError)?
Observer
OnNext* (OnCompleted|OnError)?
Observer
OnNext* (OnCompleted|OnError)?
Observer
OnNext* (OnCompleted|OnError)?
Observer
Observable.range(1, 4400)
Observer
Observable.range(1, 4400).subscribe()
Observer
Observable.range(1, 4400).subscribe(onNext)
Observer
Observable.range(1, 4400).subscribe(System.out::println)
Observer
Observable.range(1, 4400).subscribe(System.out::println, onError)
Observer
Observable.range(1, 4400).subscribe(System.out::println, System.err::println)
Observer
Observable.range(1, 4400).subscribe(System.out::println, System.err::println,onCompleted)
Observer
Observable.range(1, 4400).subscribe(System.out::println, System.err::println,
() -> System.out.println(“finished”))
Manipulation d’évènements
Quand l’écoute ne suffit plus
Manipulation d’évènements
0 1
Manipulation d’évènements
0 1
map
Manipulation d’évènements
0 1
A B
map
Manipulation d’évènements
1 4
Manipulation d’évènements
1 4
filter ( x <= 2 )
Manipulation d’évènements
1 4
1
filter ( x <= 2 )
Manipulation d’évènements
1 2
Manipulation d’évènements
1 2
delay ( 5, SECONDS )
Manipulation d’évènements
1 2
1
delay ( 5, SECONDS )
2
Manipulation d’évènements
Observable.from(0, 1, 2, 3, 4)
Observable<Integer>
Manipulation d’évènements
Observable.from(0, 1, 2, 3, 4) .filter((i) -> i < 3)
Observable<Integer>Observable<Integer>
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>
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>
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>
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>
Manipulation d’évènements
Manipulation d’évènements
Manipulation d’évènements
Composition
Création d’un flux à partir d’un ensemble de flux
Composition
Composition
Composition
Mise en pratique de composition
Learn from the trenches
Composition
Composition
Composition
Composition
Composition
Composition
merge
Composition
merge
Composition
Composition
Composition
zip
Composition
zip
Subscription
Et gestion de l’unsubscribe
Subscription
Observable.create(new OnSubscribe<T>() { … });
Subscription
Observable.create(new OnSubscribe<T>() {
@Override public void call(Subscriber<? super T> s) { s.onNext(123); s.onCompleted(); }
});
Subscription
Observable.create(new OnSubscribe<T>() {
@Override public void call(Subscriber<? super T> s) { s.onNext(123); s.onCompleted(); }
});
Émission synchronne
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); } }); }});
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); } }); }});
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); } }); }});
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
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
Subscription
La souscription permet d’uniformiser des API différentes par leurs natures (Callback, etc...)
Unsubscribe
Subscription subscription = Observable.interval(1, TimeUnit.SECONDS).subscribe();
Unsubscribe
Subscription subscription = Observable.interval(1, TimeUnit.SECONDS).subscribe();
Souscription
Unsubscribe
Subscription subscription = Observable.interval(1, TimeUnit.SECONDS).subscribe();
Handler sur la souscription
Unsubscribe
Subscription subscription = Observable.interval(1, TimeUnit.SECONDS).subscribe();/* ... */subscription.unsubscribe();
Unsubscribe
Subscription subscription = Observable.interval(1, TimeUnit.SECONDS).subscribe();/* ... */subscription.unsubscribe();
Arrêt de la souscription
Schedulers
Schedulers
observableReadingSynchronously(“strings.txt”)
.take(10) .delay(1, SECONDS) .map(parse())
.map(n -> “=> ” + n)) .subscribe(to_the_view())
Schedulers
main
Schedulers
observableReadingSynchronously(“strings.txt”)
.take(10) .delay(1, SECONDS) .map(parse())
.map(n -> “=> ” + n)) .subscribe(to_the_view())
Schedulers
Computation
IO
UI
main
Schedulers
Computation
IO
UI
main
Schedulers
Computation
IO
UI
main
Schedulers
Computation
IO
UI
main
Schedulers
Computation
IO
UI
main
Schedulers
Computation
IO
UI
main
Schedulers
observableReadingSynchronously(“strings.txt”) .subscribeOn(scheduler) .take(10) .delay(1, SECONDS, scheduler) .map(parse()) .observeOn(scheduler) .map(n -> “=> ” + n)) .subscribe(to_the_view())
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())
Schedulers
UI
Computation
Schedulers
UI
Computation
Schedulers
UI
Computation
Schedulers
UI
Computation
Schedulers
UI
Computation
Hot & Cold Observable
Cold Observable
Observable<Integer> obs = Observable.from(1, 2, 3, 4);
obs.subscribe(System.out::println);
obs.subscribe(System.out::println);
Cold Observable
Observable<Integer> obs = Observable.from(1, 2, 3, 4);
obs.subscribe(System.out::println);
obs.subscribe(System.out::println);
Cold Observable
Observable<Integer> obs = Observable.from(1, 2, 3, 4);
obs.subscribe(System.out::println);
obs.subscribe(System.out::println);
Subscribe
Cold Observable
Observable<Integer> obs = Observable.from(1, 2, 3, 4);
obs.subscribe(System.out::println);
obs.subscribe(System.out::println); Subscribe
Cold Observable
Observable<Integer> obs = Observable.from(1, 2, 3, 4);
obs.subscribe(System.out::println);
obs.subscribe(System.out::println);Souscription différente
Hot Observable
ConnectableObservable<Integer> obs = Observable.from(1, 2, 3, 4).publish();
obs.subscribe(System.out::println);
obs.subscribe(System.out::println);
obs.connect();
Hot Observable
ConnectableObservable<Integer> obs = Observable.from(1, 2, 3, 4).publish();
obs.subscribe(System.out::println);
obs.subscribe(System.out::println);
obs.connect();
Hot Observable
ConnectableObservable<Integer> obs = Observable.from(1, 2, 3, 4).publish();
obs.subscribe(System.out::println);
obs.subscribe(System.out::println);
obs.connect();
Hot Observable
ConnectableObservable<Integer> obs = Observable.from(1, 2, 3, 4).publish();
obs.subscribe(System.out::println);
obs.subscribe(System.out::println);
obs.connect();
Hot Observable
ConnectableObservable<Integer> obs = Observable.from(1, 2, 3, 4).publish();
obs.subscribe(System.out::println);
obs.subscribe(System.out::println);
obs.connect();
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
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
Hot Observable
ConnectableObservable<Integer> obs = Observable.from(1, 2, 3, 4).publish();
obs.subscribe(System.out::println);
obs.subscribe(System.out::println);
obs.connect();
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
Cold & Hot Observable
Cold Observable = flux passif
Hot Observable = flux actif
Back Pressure
Contrôler la production
Back Pressure
Production
Back Pressure
Production
buffer
Back Pressure
Production
Pression arrière
Back Pressure
Production
Pression arrière
Demande de production de n élements
Retour d’expérience
Opérateurs
Observable.from(1, 2, 3, 4) .reduce(new LinkedList<Integer>(), (seed, value) -> { seed.add(value); return seed; }) .first() .subscribe(System.out::println);
Opérateurs
Observable.from(1, 2, 3, 4) .reduce(new LinkedList<Integer>(), (seed, value) -> { seed.add(value); return seed; }) .first() .subscribe(System.out::println);
Opérateurs
Observable.from(1, 2, 3, 4) .toList() .first() .subscribe(System.out::println);
Opérateurs
Observable.from(1, 2, 3, 4) .toList() .first() .subscribe(System.out::println);
Opérateurs
Observable.from(1, 2, 3, 4) .toList() .first() .subscribe(System.out::println);
Différence entre first() / single() / take(1) ?
Gestion des erreurs
Observable.from(1, 2, 3, 4) .toList() .single() .subscribe(System.out::println);
Gestion des erreurs
Observable.from(1, 2, 3, 4) .toList() .single() .subscribe(System.out::println);
Notification des erreurs absentes
Gestion des erreurs
static { RxJavaPlugins.getInstance().registerErrorHandler(new RxJavaErrorHandler() { @Override public void handleError(Throwable e) { e.printStackTrace(); } });}
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); } });
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
Lambda & Java 8
Observable.from(1, 2, 3, 4) .filter(i -> i > 3) .subscribe(System.out::println);
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
Concurrence
obs1.mergeWith(obs2) .take(5) .subscribe(System.out::println);
Concurrence
obs1.mergeWith(obs2) .take(5) .subscribe(System.out::println);
Concurrence
obs1.mergeWith(obs2) .take(5) .subscribe(System.out::println);
Doit gérer la concurrence
Concurrence
obs1.mergeWith(obs2) .take(5) .subscribe(System.out::println);
Concurrence
obs1.mergeWith(obs2) .take(5) .subscribe(System.out::println);
non concurrence
Sync & Async
Observable<Integer> generator();
Sync & Async
Observable<Integer> generator();
Sync ?
Sync & Async
Observable<Integer> generator();
Sync ? Async ?
Sync & Async
Observable<Integer> generator();
Sync ? Async ?
Computation ?
Sync & Async
Observable<Integer> generator();
Sync ? Async ?
Computation ? Acteur ?
“Leak” des Observables
everything is an event
“Leak” des Observables
ViewPager
“Leak” des Observables
ViewPager
Preferences
Observable
“Leak” des Observables
ViewPager
Preferences
UserService
Observable
Observable
Future<RxJava>
Future<RxJava>
Support RxJava
Reactive Streams
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/
Reactive Streams
RxJava | Akka Streams | Reactor Composable | Ratpack
Reactive Streams
RxJava | Akka Streams | Reactor Composable | Ratpack
> 700 Ko | Java | Android
Reactive Streams
RxJava | Akka Streams | Reactor Composable | Ratpack
> 2.5 Mo | Scala | Akka
Reactive Streams
RxJava | Akka Streams | Reactor Composable | Ratpack
~1Mo | Java | RingBufferDispatcher
Reactive Streams
RxJava | Akka Streams | Reactor Composable | Ratpack
Java 8 | Http
Si il ne fallait retenir qu’une chose
Si il ne fallait retenir qu’une chose
RxJava est un modèle de programmation pour écrire des applications asynchrones
Frontend | Backend | Crossplatform
Questions ?
david.wursteisen@soat.fr@dwursteisen
top related