Last active
May 13, 2020 07:57
-
-
Save ConorGarry/234ea2c449db2470660853bb87bd7769 to your computer and use it in GitHub Desktop.
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 characters
| import androidx.lifecycle.LiveData | |
| import androidx.lifecycle.MutableLiveData | |
| import androidx.lifecycle.ViewModel | |
| import androidx.lifecycle.viewModelScope | |
| import kotlinx.coroutines.* | |
| import kotlin.coroutines.AbstractCoroutineContextElement | |
| import kotlin.coroutines.CoroutineContext | |
| class CoroutineApiViewModel : ViewModel() { | |
| private val _dataOne = MutableLiveData<UiState<String>>() | |
| val dataOne: LiveData<UiState<String>> = _dataOne | |
| private val _dataTwo = MutableLiveData<UiState<String>>() | |
| val dataTwo: LiveData<UiState<String>> = _dataTwo | |
| private val _dataThree = MutableLiveData<UiState<String>>() | |
| val dataThree: LiveData<UiState<String>> = _dataThree | |
| init { | |
| viewModelScope.launch { | |
| supervisorScope { | |
| _dataOne.repoFetch(this) { getDataOne() } | |
| _dataTwo.repoFetch(this) { getDataTwo() } | |
| _dataThree.repoFetch(this) { getDataThree() } | |
| } | |
| } | |
| } | |
| /** | |
| * Ext function on MutableLiveData<UiState<T>>. | |
| * For streamlining common pattern for fetching data from repo and | |
| * setting state either to Success with fetched data, or Error. | |
| * | |
| * @param scope CoroutineScope For launching coroutine (should be [supervisorScope] | |
| * if used concurrently with other coroutines). | |
| * @param f Function Suspend function that fetches data from repo. | |
| * @param dispatcher CoroutineDispatcher Defaults to IO. | |
| */ | |
| suspend fun <T> MutableLiveData<UiState<T>>.repoFetch( | |
| scope: CoroutineScope, | |
| dispatcher: CoroutineDispatcher = Dispatchers.IO, | |
| f: suspend () -> T, | |
| ) { | |
| scope.launch(dispatcher + UiStateExceptionHandler(this)) { | |
| postValue(UiState.Success(f())) | |
| } | |
| } | |
| /** | |
| * CoroutineExceptionHandler for catching Exceptions and posting them to the LiveData State holder. | |
| * @param state MutableLiveData<UiState<T>> State object for propagating Success data or Error Throwable to. | |
| */ | |
| @Suppress("FunctionName") | |
| public fun <T> UiStateExceptionHandler(state: MutableLiveData<UiState<T>>): CoroutineExceptionHandler { | |
| return object : AbstractCoroutineContextElement(CoroutineExceptionHandler), CoroutineExceptionHandler { | |
| override fun handleException(context: CoroutineContext, exception: Throwable) { | |
| state.postValue(UiState.Error(exception)) | |
| } | |
| } | |
| } | |
| suspend fun getDataOne(): String { | |
| delay(200) | |
| return "Data One Payload." | |
| } | |
| suspend fun getDataTwo(): String { | |
| delay(200) | |
| error("Runtime error while fetching data two!") | |
| return "Data Two Payload." | |
| } | |
| suspend fun getDataThree(): String { | |
| delay(200) | |
| return "Data Three Payload." | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment