Skip to content

How to perform exception handling in the coroutines

Devrath edited this page Jun 15, 2021 · 1 revision
  • This use case demonstrates different ways of handling exceptions using try/catch and CoroutineExceptionHandler.
  • It also demonstrates when you should use supervisorScope{}: In situations when you don't want a failing coroutine to cancel its sibling coroutines.
  • In one implementation of this use case, the results of the successful responses are shown even though one response wasn't successful.
class ExceptionHandlingViewModel(
    private val api: MockApi = mockApi()
) : BaseViewModel<UiState>() {

    fun handleExceptionWithTryCatch() {
        uiState.value = UiState.Loading
        viewModelScope.launch {
            try {
                api.getAndroidVersionFeatures(27)

            } catch (exception: Exception) {
                uiState.value = UiState.Error("Network Request failed: $exception")
            }
        }
    }

    fun handleWithCoroutineExceptionHandler() {
        val exceptionHandler = CoroutineExceptionHandler { _, exception ->
            uiState.value = UiState.Error("Network Request failed!! $exception")
        }

        uiState.value = UiState.Loading
        viewModelScope.launch(exceptionHandler) {
            api.getAndroidVersionFeatures(27)
        }
    }

    fun showResultsEvenIfChildCoroutineFails() {
        uiState.value = UiState.Loading
        viewModelScope.launch {


            //supervisorScope {
            val oreoFeaturesDeferred = async { api.getAndroidVersionFeatures(27) }
            val pieFeaturesDeferred = async { api.getAndroidVersionFeatures(28) }
            val android10FeaturesDeferred = async { api.getAndroidVersionFeatures(29) }

            val versionFeatures = listOf(
                oreoFeaturesDeferred,
                pieFeaturesDeferred,
                android10FeaturesDeferred
            ).mapNotNull {
                try {
                    it.await()
                } catch (exception: Exception) {
                    // We have to re-throw cancellation exceptions so that
                    // our Coroutine gets cancelled immediately.
                    // Otherwise, the CancellationException is ignored
                    // and the Coroutine keeps running until it reaches the next
                    // suspension point.
                    if (exception is CancellationException) {
                        throw exception
                    }
                    Timber.e("Error loading feature data!")
                    null
                }
            }
            uiState.value = UiState.Success(versionFeatures)
            //}
        }
    }
}
Clone this wiki locally