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
Javier Gamarra
November 30, 2015
Programming
1
310
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
100
2000 katas later @CAS15
nhpatt
0
93
Métricas: lo bueno, lo feo y lo malo
nhpatt
0
210
Working Effectively with Legacy Code
nhpatt
0
360
Performance myths in android
nhpatt
2
250
How *not* to design an SDK
nhpatt
0
42
Angular2 @SC Toledo
nhpatt
0
52
Cambiar una empresa con juegos ágiles
nhpatt
0
240
Android M
nhpatt
0
66
Other Decks in Programming
See All in Programming
CNCF Project の作者が考えている OSS の運営
utam0k
5
550
令和7年版 あなたが使ってよいフロントエンド機能とは
mugi_uno
12
5.9k
DevinとCursorから学ぶAIエージェントメモリーの設計とMoatの考え方
itarutomy
1
450
HTML/CSS超絶浅い説明
yuki0329
0
200
DevFest - Serverless 101 with Google Cloud Functions
tunmise
0
140
定理証明プラットフォーム lapisla.net
abap34
1
600
ペアーズでの、Langfuseを中心とした評価ドリブンなリリースサイクルのご紹介
fukubaka0825
1
160
watsonx.ai Dojo #6 継続的なAIアプリ開発と展開
oniak3ibm
PRO
0
250
個人アプリを2年ぶりにアプデしたから褒めて / I just updated my personal app, praise me!
lovee
0
270
混沌とした例外処理とエラー監視に秩序をもたらす
morihirok
18
3k
functionalなアプローチで動的要素を排除する
ryopeko
1
750
Lookerは可視化だけじゃない。UIコンポーネントもあるんだ!
ymd65536
1
130
Featured
See All Featured
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
232
17k
Music & Morning Musume
bryan
46
6.3k
The Power of CSS Pseudo Elements
geoffreycrofte
74
5.4k
Writing Fast Ruby
sferik
628
61k
Rails Girls Zürich Keynote
gr2m
94
13k
Build The Right Thing And Hit Your Dates
maggiecrowley
33
2.5k
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
132
33k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
248
1.3M
Facilitating Awesome Meetings
lara
51
6.2k
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
44
9.4k
How to Ace a Technical Interview
jacobian
276
23k
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
39
1.9k
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