Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
RxJava in practice
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
Javier Gamarra
November 30, 2015
Programming
1
330
RxJava in practice
Slides for a workshop about RxJava & RxAndroid delivered at the Codemotion 2015.
Javier Gamarra
November 30, 2015
Tweet
Share
More Decks by Javier Gamarra
See All by Javier Gamarra
2000 katas later @cylicon
nhpatt
0
110
2000 katas later @CAS15
nhpatt
0
97
Métricas: lo bueno, lo feo y lo malo
nhpatt
0
240
Working Effectively with Legacy Code
nhpatt
0
410
Performance myths in android
nhpatt
2
280
How *not* to design an SDK
nhpatt
0
48
Angular2 @SC Toledo
nhpatt
0
56
Cambiar una empresa con juegos ágiles
nhpatt
0
250
Android M
nhpatt
0
72
Other Decks in Programming
See All in Programming
LLM Observabilityによる 対話型音声AIアプリケーションの安定運用
gekko0114
2
420
AI 駆動開発ライフサイクル(AI-DLC):ソフトウェアエンジニアリングの再構築 / AI-DLC Introduction
kanamasa
12
6.5k
Oxlintはいいぞ
yug1224
5
1.3k
プロダクトオーナーから見たSOC2 _SOC2ゆるミートアップ#2
kekekenta
0
200
Oxlint JS plugins
kazupon
1
530
AgentCoreとHuman in the Loop
har1101
5
220
MDN Web Docs に日本語翻訳でコントリビュート
ohmori_yusuke
0
640
Vibe codingでおすすめの言語と開発手法
uyuki234
0
220
Grafana:建立系統全知視角的捷徑
blueswen
0
320
React 19でつくる「気持ちいいUI」- 楽観的UIのすすめ
himorishige
11
5.9k
0→1 フロントエンド開発 Tips🚀 #レバテックMeetup
bengo4com
0
540
そのAIレビュー、レビューしてますか? / Are you reviewing those AI reviews?
rkaga
6
4.5k
Featured
See All Featured
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
25
1.7k
Highjacked: Video Game Concept Design
rkendrick25
PRO
1
280
Build your cross-platform service in a week with App Engine
jlugia
234
18k
YesSQL, Process and Tooling at Scale
rocio
174
15k
Java REST API Framework Comparison - PWX 2021
mraible
34
9.1k
コードの90%をAIが書く世界で何が待っているのか / What awaits us in a world where 90% of the code is written by AI
rkaga
60
42k
Mind Mapping
helmedeiros
PRO
0
75
Docker and Python
trallard
47
3.7k
Efficient Content Optimization with Google Search Console & Apps Script
katarinadahlin
PRO
0
310
DevOps and Value Stream Thinking: Enabling flow, efficiency and business value
helenjbeal
1
89
Digital Projects Gone Horribly Wrong (And the UX Pros Who Still Save the Day) - Dean Schuster
uxyall
0
290
The Pragmatic Product Professional
lauravandoore
37
7.1k
Transcript
MADRID · NOV 27-28 · 2015 RxJava in practice Javier
Gamarra
MADRID · NOV 27-28 · 2015 http://kcy.me/29crj (slides) & http://kcy.me/296bu
(commits)
MADRID · NOV 27-28 · 2015 Environment Eclipse | Android
Studio (RxAndroid) RxJava.jar [Java 8] || [Retrolambda] :P
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
MADRID · NOV 27-28 · 2015 Github • http://kcy.me/296bu •
koans • código • commit a commit • Podéis preguntarme en cualquier momento
MADRID · NOV 27-28 · 2015 Who? Javier Gamarra /
@nhpatt @liferay @cyliconvalley / @agilespain
MADRID · NOV 27-28 · 2015 Ask! Please? Pretty please?
Please pretty please with sugar on top?
MADRID · NOV 27-28 · 2015 Background?
MADRID · NOV 27-28 · 2015 Why?
MADRID · NOV 27-28 · 2015 Why? (in java) multithreading
is hard futures are complicated callbacks are hell
MADRID · NOV 27-28 · 2015 Rx comes to the
rescue!
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
MADRID · NOV 27-28 · 2015 a library
MADRID · NOV 27-28 · 2015 A library? Extensions to
.NET framework Netflix
MADRID · NOV 27-28 · 2015 Libraries are tools If
all you have is a hammer, everything looks like a nail
MADRID · NOV 27-28 · 2015 a library to model
Observables & Subscribers
MADRID · NOV 27-28 · 2015 Observables and Subscribers An
Observable emits items. A Subscriber consumes those items.
MADRID · NOV 27-28 · 2015 Observer pattern?
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(); } });
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); } };
MADRID · NOV 27-28 · 2015 My very first subscription
myObs.subscribe(mySubs);
MADRID · NOV 27-28 · 2015 A bit verbose... Let’s
simplify with Java8 and RxJava • lamdbas • Observable.just • .subscribe()
MADRID · NOV 27-28 · 2015 That’s better... Observable .just("Hi!")
.subscribe(System.out::println);
MADRID · NOV 27-28 · 2015 Why? More than the
observer pattern • Observables only emit when someone listening • OnFinished • OnError
MADRID · NOV 27-28 · 2015 Let’s use those differences
subscribe admits 3 parameters • OnNext • OnFinished • OnError
MADRID · NOV 27-28 · 2015 You said “items” Observable.from
admits a list of elements
MADRID · NOV 27-28 · 2015 Ok, let’s recap… Iterators?
MADRID · NOV 27-28 · 2015 Iterators? • Iterators are
pull and synchronous • Subscribers are push and asynchronous
MADRID · NOV 27-28 · 2015 to represent any operation
as an “asynchronous data stream”
MADRID · NOV 27-28 · 2015 Everything is a stream
MADRID · NOV 27-28 · 2015 Everything is a stream
We can model everything as a stream
MADRID · NOV 27-28 · 2015 Everything is a stream
A network call is also a stream Like using retrofit with this API
MADRID · NOV 27-28 · 2015 “declaratively composed”
MADRID · NOV 27-28 · 2015 Operators
MADRID · NOV 27-28 · 2015 Operators Transform a stream
rxmarbles and android app
MADRID · NOV 27-28 · 2015 Operators Map
MADRID · NOV 27-28 · 2015 Map List<String> severalThings =
Arrays.asList("1", "2"); Observable.from(severalThings) .map((s) -> “Element “ + s) .subscribe(System.out::println);
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);
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
MADRID · NOV 27-28 · 2015 Flatmap Flatmap Obs ->
elements
MADRID · NOV 27-28 · 2015 Flatmap service.listRepos("nhpatt") .flatMap(Observable::from) .map(Repo::getName)
.map((s) -> s.replace("-", " ")) .subscribe(System.out::println);
MADRID · NOV 27-28 · 2015 Flatmap Concatmap -> ordered
flatmap
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);
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);
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;
MADRID · NOV 27-28 · 2015 Operators • merge •
flatMap • zip Nice things™ : parallel jobs!
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()); });
MADRID · NOV 27-28 · 2015 Operators Amazing documentation •
Async • Blocking • Combining • Conditional • Error handling • Filtering • Mathematical • Creation • String • Transforming • Utility
MADRID · NOV 27-28 · 2015 Subscribers are asynchronous? No,
not really
MADRID · NOV 27-28 · 2015 “on any thread”
MADRID · NOV 27-28 · 2015 Schedulers!
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 ...
MADRID · NOV 27-28 · 2015 Schedulers .subscribeOn(Schedulers...) .observeOn(Schedulers...) •
io • computation • newThread • trampoline • test
MADRID · NOV 27-28 · 2015 Schedulers service.listRepos("nhpatt") .subscribeOn(Schedulers.immediate()) .observeOn(Schedulers.immediate())
.subscribe(System.out::println);
MADRID · NOV 27-28 · 2015 Schedulers RxJava operators have
default threads Interval?
MADRID · NOV 27-28 · 2015 Use cases?
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
MADRID · NOV 27-28 · 2015 Android?
MADRID · NOV 27-28 · 2015 Why?
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
MADRID · NOV 27-28 · 2015 How RxAndroid helps?
MADRID · NOV 27-28 · 2015 Android schedulers service.listRepos("nhpatt") .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread()) .subscribe(newRepos -> { repos.addAll(newRepos); adapter.notifyDataSetChanged(); });
MADRID · NOV 27-28 · 2015 Orientation Problem Orientation Problem
• onCreate gets called again • state is lost
MADRID · NOV 27-28 · 2015 Orientation Problem Programmer’s job:
• Store/Restore state • Restore view • Call again the user task? • Wait until it finishes?
MADRID · NOV 27-28 · 2015 How RxAndroid helps?
MADRID · NOV 27-28 · 2015 Orientation Problem Observable is
easy to persist (retain | singleton) Observable can continue (cache and retry) RxLifecycle
MADRID · NOV 27-28 · 2015 Orientation Problem Observable<List<Repo>> github
= RetrofitService. getGithub() .listRepos("nhpatt") .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .cache();
MADRID · NOV 27-28 · 2015 More Android Lifecycle (RxLifecyle)
Views (RxBinding)
MADRID · NOV 27-28 · 2015 But...
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
MADRID · NOV 27-28 · 2015 Easy to unsubscribe @Override
protected void onStop() { super.onStop(); subscription.unsubscribe(); } .isUnsubscribed() :(
MADRID · NOV 27-28 · 2015 Let’s recap
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
MADRID · NOV 27-28 · 2015 a library to represent
any operation as an observable on any thread, declaratively composed, and consumed by multiple objects
MADRID · NOV 27-28 · 2015 a library to represent
any operation as an observable with schedulers declaratively composed, and consumed by multiple objects
MADRID · NOV 27-28 · 2015 a library to represent
any operation as an observable with schedulers and operators and consumed by multiple objects
MADRID · NOV 27-28 · 2015 a library to represent
any operation as an observable with schedulers and operators listened by subscribers
MADRID · NOV 27-28 · 2015 But...
MADRID · NOV 27-28 · 2015 But... • Learning curve
• Hard to debug (Frodo library) • Backpressure
MADRID · NOV 27-28 · 2015 Questions?
MADRID · NOV 27-28 · 2015 Where to know more...
• reactivex.io (amazing docs) • RxJava wiki • Dan Lew • Use cases
MADRID · NOV 27-28 · 2015 Where to know more...
nhpatt (twitter | github | email | slack) I’ll do anything for good votes
MADRID · NOV 27-28 · 2015 Feedback Click here :P
MADRID · NOV 27-28 · 2015 RxJava in practice Javier
Gamarra
MADRID · NOV 27-28 · 2015 Other interesting operators...
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);
MADRID · NOV 27-28 · 2015 Operators distinctUntilChanged compose
MADRID · NOV 27-28 · 2015 Errors?
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
MADRID · NOV 27-28 · 2015 Errors And we can
customize the flow: onErrorResumeNext onErrorReturn retry ...
MADRID · NOV 27-28 · 2015 Why this is useful?
MADRID · NOV 27-28 · 2015 Why this is useful?
Observables and subscribers can do anything
MADRID · NOV 27-28 · 2015 Why this is useful?
Observable a database query Subscriber displaying results on the screen
MADRID · NOV 27-28 · 2015 Why this is useful?
Observable a click on the screen Subscriber reacting to it
MADRID · NOV 27-28 · 2015 Why this is useful?
Observable a stream of bytes from the internet Subscriber write them to disk
MADRID · NOV 27-28 · 2015 Why this is useful?
Observable and Subscriber are independent of the transformations
MADRID · NOV 27-28 · 2015 Why this is useful?
I can compose/chain any map/filter calls I want Only matters the return type
MADRID · NOV 27-28 · 2015 Side effects?
MADRID · NOV 27-28 · 2015 Side effects doOn methods:
• doOnNext() for debugging • doOnError() for error handling • doOnNext() to save/cache results
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) );
MADRID · NOV 27-28 · 2015 Side effects flatMap(id ->
service.get() .doOnError(t -> { // report problem to UI }) .onErrorResumeNext(Observable.empty()))
MADRID · NOV 27-28 · 2015 Cold & Hot
MADRID · NOV 27-28 · 2015 Cold & Hot Observables
only emit when someone listening? Cold observables only emit when subscribed But hot observables emit instantly
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()
MADRID · NOV 27-28 · 2015 Cold & Hot publish
& connect? “like transactions” Assume everything is cold
MADRID · NOV 27-28 · 2015 Testing?
MADRID · NOV 27-28 · 2015 More cool things? •
testscheduler • toIterator() • Obs.error(), Obs.empty()
MADRID · NOV 27-28 · 2015 Subjects
MADRID · NOV 27-28 · 2015 Subjects Both observable &
observer
MADRID · NOV 27-28 · 2015 Subjects AsyncSubject -> takeLast(1)
PublishSubject -> publish() ReplaySubject -> replay()/cache() BehaviorSubject -> replay(1)/cache(1)
MADRID · NOV 27-28 · 2015 RxJava in practice Javier
Gamarra