Last active
May 27, 2022 09:52
-
-
Save stantronic/3915e73f4a8faef59b7d22cb940ea292 to your computer and use it in GitHub Desktop.
Revisions
-
stantronic revised this gist
May 27, 2022 . 1 changed file with 10 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -73,3 +73,13 @@ fun getSingleResult() = viewModelScope.launch { } ``` ## Converting co-routines to Rx observables When you need to convert in the opposite direction from suspend functions to RXJava classes: * If a suspend function returns nothing (Unit) then surround with `rxCompletable { /* suspend call here */ }` * If a suspend function returns a non-nullable type then surround with `rxSingle { /* suspend call here */ }` * If a suspend function returns a nullable type then either wrap it in an optional, or use a maybe: * `rxMaybe { /* suspend call here */ }` * `rxSingle { Optional.of( /* suspend call here */ )` -
stantronic revised this gist
May 13, 2022 . 1 changed file with 21 additions and 41 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -2,52 +2,32 @@ ## Some do's and dont's | *Dont* | *Do* | |---|---| | _Dont_ call suspend functions on view-models from activities or fragments | _Do_ launch coroutines in view-models from viewModelScope | | call launch within a suspend function (unless you handle the error within the launch block) | _Do_ switch threads using withContext(dispatcher) | | _Dont_ call suspend functions on view-models from activities or fragments | _Do_ launch coroutines in view-models from viewModelScope | | _Dont_ call launch within a suspend function (unless you handle the error within the launch block) | _Do_ switch threads using withContext(dispatcher) | | _Dont_ use flow unless you need to. Rx's Single, Maybe and Completable can all be handled using regular suspend calls | _Do_ use Flows or Channels if you need to replace an Observable or Flowable | | _Dont_ use `Dispatchers.Main`, `Dispatchers.Default` or `Dispatchers.IO` directly | _Do_ inject a `CoroutineDispatcher` using the relevant custom dagger annotation: e.g. `@Ui`, `@Compute` or `@Io`. | | Retrofit uses its own dispatchers internally, so you _dont_ normally need the `@Io` dispatcher for api calls. although you might need it for file-writing operations etc. | _Do_ inject the `@Compute` coroutine dispatcher into use-cases and repositories or anything requiring intensive computation. | ## Replacements | *Instead of* | *Use* | |---|---| |`someUseCase().subscribe { /* handle data */ }` | `val data = someUseCase.await()` | | `makeRxCall().subscribeOn(schedulers.io())` |` withContext(dispatcher){ makeRxCall().await() }` | | `makeRxCall().subscribe({ handleSuccess(it)}, { handleError(it)})` | `try { /* make calls and handle success */ } catch(e: Throwable) { /* handle error */ }`| |`doOnTerminate` | `finally {}`| |`PublishSubject<T>()` | `MutableSharedFlow<T>()` | | exposing PublishSubject as `Observable<T>` | expose MutableSharedFlow as `SharedFlow<T>` | |`BehaviourSubject<T>()` | `MutableStateFlow<T>(defaultValue)` | | BehaviourSubject as `Observable<T>` |expose mutable state flow as `StateFlow<T>` | | instead of `publishSubject.accept(value)` | `mutableSharedFlow.emit(value)` (or `.tryEmit(value)` if not in suspend call) | ## Putting it all together -
stantronic revised this gist
May 13, 2022 . 1 changed file with 2 additions and 0 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -22,6 +22,8 @@ Retrofit uses its own dispatchers internally, so you _dont_ normally need the `@ for api calls; although you might need it for file-writing operations etc. ## Replacements * instead of `someUseCase().subscribe { /* handle data */ }` use `val data = someUseCase.await()` * instead of `makeRxCall().subscribeOn(schedulers.io())` -
stantronic revised this gist
May 13, 2022 . 1 changed file with 21 additions and 9 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -22,19 +22,30 @@ Retrofit uses its own dispatchers internally, so you _dont_ normally need the `@ for api calls; although you might need it for file-writing operations etc. * instead of `someUseCase().subscribe { /* handle data */ }` use `val data = someUseCase.await()` * instead of `makeRxCall().subscribeOn(schedulers.io())` use ` withContext(dispatcher){ makeRxCall().await() }` * instead of `makeRxCall().subscribe({ handleSuccess(it)}, { handleError(it)})` use `try { /* make calls and handle success */ } catch(e: Throwable) { /* handle error */ }` * instead of `doOnTerminate` use `finally {}` * instead of `PublishSubject<T>()` use `MutableSharedFlow<T>()` * instead of exposing PublishSubject as `Observable<T>` expose MutableSharedFlow as `SharedFlow<T>` * instead of `BehaviourSubject<T>()` use `MutableStateFlow<T>(defaultValue)` * instead of exposing BehaviourSubject as `Observable<T>` expose mutable state flow as `StateFlow<T>` * instead of `publishSubject.accept(value)` use `mutableSharedFlow.emit(value)` (or `.tryEmit(value)` if not in suspend call) ## Putting it all together @@ -65,6 +76,7 @@ fun getSingleResult() { // With co-routines it becomes: fun getSingleResult() = viewModelScope.launch { loading.postValue(true) try { -
stantronic created this gist
May 13, 2022 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,81 @@ # Rx Java to Coroutines Cheat Sheet ## Some do's and dont's * _Dont_ call suspend functions on view-models from activities or fragments * _Do_ launch coroutines in view-models from viewModelScope * _Dont_ call launch within a suspend function (unless you handle the error within the launch block) * _Do_ switch threads using withContext(dispatcher) * _Dont_ use flow unless you need to. * Rx's Single, Maybe and Completable can all be handled using regular suspend calls * Use Flows or Channels if you need to replace an Observable or Flowable * _Dont_ use `Dispatchers.Main`, `Dispatchers.Default` or `Dispatchers.IO` directly * _Do_ inject a `CoroutineDispatcher` using the relevant custom dagger annotation: e.g. `@Ui`, `@Compute` or `@Io`. * _Do_ inject the `@Compute` coroutine dispatcher into use-cases and repositories or anything requiring intensive computation. Retrofit uses its own dispatchers internally, so you _dont_ normally need the `@Io` dispatcher for api calls; although you might need it for file-writing operations etc. instead of `someUseCase().subscribe { /* handle data */ }` use `val data = someUseCase.await()` instead of `makeRxCall().subscribeOn(schedulers.io())` use ` withContext(dispatcher){ makeRxCall().await() }` instead of `makeRxCall().subscribe({ handleSuccess(it)}, { handleError(it)})` use `try { /* make calls and handle success */ } catch(e: Throwable) { /* handle error */ }` instead of `doOnTerminate` use `finally {}` instead of `PublishSubject<T>()` use `MutableSharedFlow<T>()` instead of exposing PublishSubject as `Observable<T>` expose MutableSharedFlow as `SharedFlow<T>` instead of `BehaviourSubject<T>()` use `MutableStateFlow<T>(defaultValue)` instead of exposing BehaviourSubject as `Observable<T>` expose mutable state flow as `StateFlow<T>` instead of `publishSubject.accept(value)` use `mutableSharedFlow.emit(value)` (or `.tryEmit(value)` if not in suspend call) ## Putting it all together ```kotlin // given a use-case like this: interface SomeUseCase { operator fun invoke(): Single<SomeResult> } // in a viewmodel using rx it might look like this: fun getSingleResult() { someUseCase() .subscribeOn(schedulers.io()) .doOnSubscribe { loading.postValue(true) } .doOnTerminate { loading.postValue(false) } .subscribeBy( onSuccess = { result -> liveData.postValue(result) }, onError = { errors.postValue() } ) .addTo(susbcriptions) } // With co-routines it becomes: fun getSingleResult() = viewModelScope.launch { loading.postValue(true) try { val result = someUseCase().await() liveData.postValue(result) } catch (e: Throwable) { errors.postValue(e) } finally { loading.postValue(false) } } ```