Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Trip into the async world @ NYC Kotlin Meetup

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
Tweet

More Decks by Roberto Orgiu

Other Decks in Programming

Transcript

  1. Rob

  2. @Test fun test() { runBlocking { val response = api.networkRequest()

    assertThat(response)... } api.networkRequest() .test() .assertValue { } }
  3. 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() } }
  4. 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
  5. 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
  6. 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)) } } } }
  7. 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)) } } } }
  8. 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)) } }
  9. @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(); } } }); } }); }
  10. @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() } }
  11. 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() } }
  12. val job = Job() val scope = CoroutineScope(Dispatchers.IO + job)

    fun doThings() { scope.launch { ... } } fun inTheEnd() { job.cancel() }
  13. val job = Job() val scope = CoroutineScope(Dispatchers.IO + job)

    fun doThings() { scope.launch { ... } } fun inTheEnd() { job.cancelChildren() scope.coroutineContext.cancelChildren() }
  14. 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) } }