RxJava 
Getting Started 
David Wursteisen 16 Octobre 2014
David Wursteisen 
Direction Expertise Innovation 
@dwursteisen
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 
Observable<json> json json 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 
map 
A B
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 
delay ( 5, SECONDS ) 
1 
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 
Souscription 
Subscription subscription = Observable.interval(1, TimeUnit.SECONDS).subscribe();
Unsubscribe 
Handler sur la souscription 
Subscription subscription = Observable.interval(1, TimeUnit.SECONDS).subscribe();
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 
main 
IO 
Computation 
UI
Schedulers 
main 
IO 
Computation 
UI
Schedulers 
main 
IO 
Computation 
UI
Schedulers 
main 
IO 
Computation 
UI
Schedulers 
main 
IO 
Computation 
UI
Schedulers 
main 
IO 
Computation 
UI
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 
Computation 
UI
Schedulers 
Computation 
UI
Schedulers 
Computation 
UI
Schedulers 
Computation 
UI
Schedulers 
Computation 
UI
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); 
Subscribe 
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); 
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); 
Subscribe 
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(); 
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(); 
Souscription 
obs.subscribe(System.out::println); 
obs.subscribe(System.out::println);
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 
Demande de production de n élements 
Production 
Pression arrière
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) 
Doit gérer la concurrence 
.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); 
non concurrence
Sync & Async 
Observable<Integer> generator();
Sync & Async 
Observable<Integer> generator(); 
Sync ?
Sync & Async 
Sync ? Async ? 
Observable<Integer> generator();
Sync & Async 
Sync ? Async ? 
Observable<Integer> generator(); 
Computation ?
Sync & Async 
Sync ? Async ? 
Observable<Integer> generator(); 
Computation ? Acteur ?
“Leak” des Observables 
everything is an event
“Leak” des Observables 
ViewPager
“Leak” des Observables 
ViewPager 
Observable 
Preferences
“Leak” des Observables 
ViewPager 
Observable 
Preferences 
Observable 
UserService
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

RxJava, Getting Started - David Wursteisen - 16 Octobre 2014