Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Trip into the async world @ NYC Kotlin Meetup
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
Roberto Orgiu
October 16, 2019
Programming
140
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Trip into the async world @ NYC Kotlin Meetup
These are the slides of my talk from NYC Kotlin Meetup @ Dropbox
Roberto Orgiu
October 16, 2019
More Decks by Roberto Orgiu
See All by Roberto Orgiu
Wellness & Droid
tiwiz
0
140
Behind the curtains
tiwiz
0
94
The Importance of Being Tested
tiwiz
0
460
An Android Dev start to Kotlin MPP
tiwiz
0
210
Fantastic API and where to find them
tiwiz
0
120
Flipping the Koin @ GDG Dev Party
tiwiz
1
83
Flipping the Koin
tiwiz
2
190
Trip into the async world
tiwiz
1
160
GraphQL IRL (Android Makers)
tiwiz
0
170
Other Decks in Programming
See All in Programming
SONY CISC-NEWS NWS-1750 + NWB-225 フレームバッファの NetBSD/news68k ドライバ実装 / OSC2026Hiroshima
tsutsui
0
160
KiroのSpecで「五目並べ」を作ってみる
satoshi256kbyte
1
310
Findy - エンジニア向け会社紹介/Findy Company Deck
findyinc
6
400k
The Rails Doctrine Decade
koic
2
420
モジュールの視点からSwiftを読み解く #iosdc
s_shimotori
0
260
Go × SIMDで高速化するベクトル検索 ~ルーフラインモデルでSIMDが効く境界を探れ! ~
po3rin
1
5k
フロントエンドUIフレームワークのこれまでとこれから
ssssota
5
3.1k
20260914 AIエージェント時代のPlatform Engineering LLM基盤とプロダクトの責務境界線
kanfab1
7
2.3k
技術的負債を組織課題として解く-増えすぎたマイクロサービスとの戦い-
reimaru
1
2.5k
Augmenting AI with the Power of Jakarta EE
ivargrimstad
0
430
モデルのリファクタリングが難しいと思ったら、そもそも複雑だったのはビジネス仕様だった ? / is-the-business-domain-the-real-complexity
hatsu38
0
430
Vue Fes Japan 2026 タイムテーブル徹底解説
448jp
1
570
Featured
See All Featured
How STYLIGHT went responsive
nonsquared
100
6.3k
Reality Check: Gamification 10 Years Later
codingconduct
0
2.3k
Reflections from 52 weeks, 52 projects
jeffersonlam
356
21k
Bioeconomy Workshop: Dr. Julius Ecuru, Opportunities for a Bioeconomy in West Africa
akademiya2063
PRO
1
380
Bash Introduction
62gerente
615
220k
Mind Mapping
helmedeiros
1
380
Money Talks: Using Revenue to Get Sh*t Done
nikkihalliwell
0
510
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
133
20k
Beyond borders and beyond the search box: How to win the global "messy middle" with AI-driven SEO
davidcarrasco
3
270
Future Trends and Review - Lecture 12 - Web Technologies (1019888BNR)
signer
PRO
0
3.8k
How to Ace a Technical Interview
jacobian
280
24k
Done Done
chrislema
187
17k
Transcript
Trip into the async world
Rob
Why RxJava?
Why RxJava? Retrofit
Why RxJava? Retrofit Async ops
Why RxJava? Retrofit Async ops Basic operators
Why RxJava? Retrofit Async ops Basic operators Advanced operators
Why RxJava? Retrofit Async ops Basic operators Advanced operators
Why RxJava? Retrofit Async ops Basic operators Advanced operators
implementation ‘com.squareup.retrofit2:retrofit:2.6.1’
@GET("/path/to/resource") fun networkRequest(): Single<Data> @GET("/path/to/resource") suspend fun networkRequest(): Data
Retrofit.Builder() ... .addCallAdapterFactory(CoroutineCallAdapterFactory()) .addCallAdapterFactory(RxJava2CallAdapterFactory.create()) .build()
CoroutineCallAdapterFactory() RxJava2CallAdapterFactory.create()
@Test fun test() { runBlocking { val response = api.networkRequest()
assertThat(response)... } api.networkRequest() .test() .assertValue { } }
None
class DataViewModel()) : ViewModel() { private val subscriptions = CompositeDisposable()
val output = BehaviorSubject<LCE<Data>>.create() fun loadCurrentStatus() { disposable += store.get(BarCode.empty()) .startWith(LceLoading()) .onErrorReturn({e -> LceError(e)}) .map({data -> mapEmptyData(data)}) .observeOn(AndroidSchedulers.mainThread()) .subscribeOn(Schedulers.io()) .subscribe(output) } override fun onCleared() { disposable.clear() } }
class DataViewModel()) : ViewModel() { private val subscriptions = CompositeDisposable()
val output = BehaviorSubject<LCE<Data>>.create() fun loadCurrentStatus() { disposable += store.get(BarCode.empty()) .startWith(LceLoading()) .onErrorReturn({e -> LceError(e)}) .map({data -> mapEmptyData(data)}) .observeOn(AndroidSchedulers.mainThread()) .subscribeOn(Schedulers.io()) .subscribe(output) } override fun onCleared() { disposable.clear() } } Hidden knowledge
te val subscriptions = CompositeDisposable() utput = BehaviorSubject<LCE<Data>>.create() oadCurrentStatus() {
isposable += store.get(BarCode.empty()) .startWith(LceLoading()) .onErrorReturn({e -> LceError(e)}) .map({data -> mapEmptyData(data)}) .observeOn(AndroidSchedulers.mainThread()) .subscribeOn(Schedulers.io()) .subscribe(output) ide fun onCleared() { isposable.clear() Learning curve
class DataViewModel()) : ViewModel() { val output = MutableLiveData<Data>() fun
loadCurrentStatus() { output.postValue(LceLoading()) viewModelScope.launch { try { val data = store.get(BarCode.empty()).await() if (data.isEmpty()) { output.postValue(LceError(EmptyResultSetException())) } else { output.postValue(LceSuccess(data)) } } catch (e: Exception) { output.postValue(LceError(e)) } } } }
class DataViewModel()) : ViewModel() { val output = MutableLiveData<Data>() fun
loadCurrentStatus() { output.postValue(LceLoading()) viewModelScope.launch { try { val data = store.get(BarCode.empty()).await() if (data.isEmpty()) { output.postValue(LceError(EmptyResultSetException())) } else { output.postValue(LceSuccess(data)) } } catch (e: Exception) { output.postValue(LceError(e)) } } } }
adCurrentStatus() { output.postValue(LceLoading()) viewModelScope.launch { try { val data =
store.get(BarCode.empty()).await() if (data.isEmpty()) { output.postValue(LceError(EmptyResultSetException())) } else { output.postValue(LceSuccess(data)) } } catch (e: Exception) { output.postValue(LceError(e)) } }
map flatmap filter first last
map flatmap filter first last forEach orEmpty mapNotNull
@NotNull public static <T> Observable<Response<T>> from(@NotNull final ApolloCall<T> call) {
checkNotNull(call, "call == null"); return Observable.create(new ObservableOnSubscribe<Response<T>>() { @Override public void subscribe(final ObservableEmitter<Response<T>> emitter) throws Exception { cancelOnObservableDisposed(emitter, call); call.enqueue(new ApolloCall.Callback<T>() { @Override public void onResponse(@NotNull Response<T> response) { if (!emitter.isDisposed()) { emitter.onNext(response); } } @Override public void onFailure(@NotNull ApolloException e) { Exceptions.throwIfFatal(e); if (!emitter.isDisposed()) { emitter.onError(e); } } @Override public void onStatusEvent(@NotNull ApolloCall.StatusEvent event) { if (event == ApolloCall.StatusEvent.COMPLETED && !emitter.isDisposed()) { emitter.onComplete(); } } }); } }); }
@NotNull public static <T> Observable<Response<T>> from(@NotNull final ApolloCall<T> call) {
checkNotNull(call, "call == null"); return Observable.create(new ObservableOnSubscribe<Response<T>>() { @Override public void subscribe(final ObservableEmitter<Response<T>> emitter) throws Exception { cancelOnObservableDisposed(emitter, call); call.enqueue(new ApolloCall.Callback<T>() { @Override public void onResponse(@NotNull Response<T> response) { if (!emitter.isDisposed()) { emitter.onNext(response); } } @Override public void onFailure(@NotNull ApolloException e) { Exceptions.throwIfFatal(e); if (!emitter.isDisposed()) { emitter.onError(e); } } @Override public void onStatusEvent(@NotNull ApolloCall.StatusEvent event) { if (event == ApolloCall.StatusEvent.COMPLETED && !emitter.isDisposed()) { emitter.onComplete(); } } }); } }); } suspend fun <T> ApolloCall<T>.await(): Response<T> = suspendCancellableCoroutine { cont -> enqueue(object : ApolloCall.Callback<T>() { override fun onFailure(e: ApolloException) { cont.resumeWithException(e) } override fun onResponse(response: Response<T>) { cont.resume(response) } }) cont.invokeOnCancellation { cancel() } }
suspend fun <T> ApolloCall<T>.await(): Response<T> = suspendCancellableCoroutine { cont ->
enqueue(object : ApolloCall.Callback<T>() { override fun onFailure(e: ApolloException) { cont.resumeWithException(e) } override fun onResponse(response: Response<T>) { cont.resume(response) } }) cont.invokeOnCancellation { cancel() } }
val job = Job() val scope = CoroutineScope(Dispatchers.IO + job)
fun doThings() { scope.launch { ... } } fun inTheEnd() { job.cancel() }
val job = Job() val scope = CoroutineScope(Dispatchers.IO + job)
fun doThings() { scope.launch { ... } } fun inTheEnd() { job.cancelChildren() scope.coroutineContext.cancelChildren() }
job.cancelChildren() scope.coroutineContext.cancelChildren() public fun Job.cancelChildren(cause: CancellationException? = null) { children.forEach
{ it.cancel(cause) } } public fun CoroutineContext.cancelChildren(cause: CancellationException? = null) { this[Job]?.children?.forEach { it.cancel(cause) } }
None
kotlinx-coroutines-rx2
class RxThing { fun doStuff() : Single<MyData> }
suspend fun doThings() { val my data = rxThing.doStuff().await() }
class CoroutineThing { suspend fun doStuff() : MyData }
fun doStuff() : Single<MyData> = rxSingle { coroutineThing.doStuff() }
fun doStuff() : Single<MyData> = rxSingle(RxCoroutineExceptionHandler) { coroutineThing.doStuff() }
None
open.nytimes.com @nytdev github.com/NYTimes developers.nytimes.com
QA &