These are the slides of my talk from NYC Kotlin Meetup @ Dropbox
Trip into theasync world
View Slide
Rob
Why RxJava?
Why RxJava?Retrofit
Why RxJava?RetrofitAsync ops
Why RxJava?RetrofitAsync opsBasic operators
Why RxJava?RetrofitAsync opsBasic operatorsAdvanced operators
implementation‘com.squareup.retrofit2:retrofit:2.6.1’
@GET("/path/to/resource")fun networkRequest(): Single@GET("/path/to/resource")suspend fun networkRequest(): Data
Retrofit.Builder()....addCallAdapterFactory(CoroutineCallAdapterFactory()).addCallAdapterFactory(RxJava2CallAdapterFactory.create()).build()
CoroutineCallAdapterFactory()RxJava2CallAdapterFactory.create()
@Testfun test() {runBlocking {val response =api.networkRequest()assertThat(response)...}api.networkRequest().test().assertValue { }}
class DataViewModel()) : ViewModel() {private val subscriptions = CompositeDisposable()val output = BehaviorSubject>.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>.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>.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()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))}}
mapflatmapfilterfirstlast
mapflatmapfilterfirstlastforEachorEmptymapNotNull
@NotNull public static Observable> from(@NotNull final ApolloCall call) {checkNotNull(call, "call == null");return Observable.create(new ObservableOnSubscribe>() {@Override public void subscribe(final ObservableEmitter> emitter) throws Exception {cancelOnObservableDisposed(emitter, call);call.enqueue(new ApolloCall.Callback() {@Override public void onResponse(@NotNull Response 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 Observable> from(@NotNull final ApolloCall call) {checkNotNull(call, "call == null");return Observable.create(new ObservableOnSubscribe>() {@Override public void subscribe(final ObservableEmitter> emitter) throws Exception {cancelOnObservableDisposed(emitter, call);call.enqueue(new ApolloCall.Callback() {@Override public void onResponse(@NotNull Response 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 ApolloCall.await(): Response =suspendCancellableCoroutine { cont ->enqueue(object : ApolloCall.Callback() {override fun onFailure(e: ApolloException) {cont.resumeWithException(e)}override fun onResponse(response: Response) {cont.resume(response)}})cont.invokeOnCancellation { cancel() }}
suspend fun ApolloCall.await(): Response =suspendCancellableCoroutine { cont ->enqueue(object : ApolloCall.Callback() {override fun onFailure(e: ApolloException) {cont.resumeWithException(e)}override fun onResponse(response: Response) {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) }}
kotlinx-coroutines-rx2
class RxThing {fun doStuff() : Single}
suspend fun doThings() {val my data =rxThing.doStuff().await()}
class CoroutineThing {suspend fun doStuff() : MyData}
fun doStuff() : Single =rxSingle {coroutineThing.doStuff()}
fun doStuff() : Single =rxSingle(RxCoroutineExceptionHandler) {coroutineThing.doStuff()}
open.nytimes.com@nytdevgithub.com/NYTimesdevelopers.nytimes.com
QA&