Kotlin Coroutines – Exception Handling and Cancellation

It’s very important to handle the exception that occurs during the networking operation or any IO operations in kotlin
coroutines. So, in this tutorial, we are going to see how to handle the exceptions and how to cancel the particular job
running on the kotlin coroutines.

Before getting into this tutorial, If you are not familiar with kotlin coroutines, I strongly recommend you read another
tutorial on kotlin coroutines.

Kotlin Coroutines for Android Development

In Kotlin Coroutines, we can handle the exceptions in two ways, one is using the try/catch block, and the way is using
the CoroutineExceptionHandler. let’s see how to implement both on kotlin coroutines.

Handling Exception With Try / Catch

In this method, we can use try/ catch in the way we are using kotlin programming. But when we are working with kotlin
coroutines, we need to put the try/catch block inside the Coroutine Scope Functions.

fun handleExceptionWithTryCatch() {
    viewModelScope.launch() {
        try {
            val movies = ApiService.getInstance().getAllMovies401()
            movieList.postValue(movies)
        } catch (e: Exception) {
            Log.d("Exception", "${e.message.toString()} handled !")
        }
    }
}

In the above code, I have created a ViewModelScope, which is a Coroutines Scope Function to perform a networking
operation. The API call returns 401 Exception, In normal cases, it will crash the application. But we are using
try/catch around the API call. So the exception will be handled.

Output:

 com.example.kotlincoroutines D/Exception: HTTP 401 401 Unauthorized handled !

Handle Exception And Return Result

In some cases, we need to return the default response when the exception occurs. To do this we need to add the default
response in the catch block to return the default response. If we are using multiple operations then we need to use
separate try/catch blocks to handle to separately.

fun returnDefaultResultOnException() {
    viewModelScope.launch {
        try {
            val movie1 = try {
                ApiService.getInstance().getAllMovies()
            } catch (e: Exception) {
                listOf()
            }

            val movie2 = try {
                ApiService.getInstance().getAllMovies401()
            } catch (e: Exception) {
                listOf()
            }

            Log.d("Movie 1", movie1.toString())
            Log.d("Movie 2", movie2.toString())

        } catch (e: Exception) {
            Log.d("Exception", "${e.message.toString()} handled !")
        }

    }

}

In the above code, I am called two API calls. The first API call returns a successful response with a list of movies.
But the second API call returns 401 exceptions. So, I handled that API using the try/catch block and returned the empty
movie list as a response.

Output:

com.example.kotlincoroutines D/Movie 1: [Movie(category=Latest, imageUrl=https://www.howtodoandroid.com/images/coco.jpg, name=Coco, desc=Coco is a 2017 American 3D computer-animated musical..
    com.example.kotlincoroutines D/Movie 2: []

Handling Exception With CoroutineExceptionHandler

In this way, we need to attach the separate CoroutineExceptionHandler variable and attach this variable to Coroutine
Builder. So, when the exception occurs in the coroutine scope it will be forwarded to the exception handler.

private val handler = CoroutineExceptionHandler { _, exception ->
    Log.d("Exception", "${exception.message.toString()} handled !")
}

fun handleExceptionWithCoroutineExceptionHandler() {
    viewModelScope.launch(handler) {
        val moviesList = ApiService.getInstance().getAllMovies401()
        movieList.postValue(moviesList)
    }
}

In the above code, I have created the CoroutineExceptionHandler variable and attached that variable to
ViewModelScope. Now, The API call returns the 401 Exception. So the exception will be directed to the exception handler
to handle it.

In this way, we have a generic exception handler and attached the multiple Coroutine Builder.

Output:

com.example.kotlincoroutines D / Exception : HTTP 401 401 Unauthorized handled !

Canceling the Kotlin Coroutine

when the user leaves the screen or user wants to cancel some operation, then we need to cancel the operation running on
the coroutine scope. to do this first, we need to create a Coroutine Scope variable called *
Job*. Job
used to do operation on coroutines including canceling.

var printingJob: Job? = null

fun startPrint() {

    printingJob = viewModelScope.launch {

        try {
            for (i in 1..1000) {
                delay(20)
                println(i)
            }
        } catch (e: Exception) {
            Log.d("Exception", "${e.message.toString()} handled !")
        } finally {
            Log.d("finally", "clear all resources")
        }
    }
}

fun stopPrint() {
    printingJob?.cancel()
}

In the above code, I have created a job variable by calling the startPrint() function I will set the coroutine scope
instance into it. Once started, it will print 1 to 1000 in a delay of 20 milliseconds.

whenever we need to cancel the job need to call the stopPrint() function to call the cancel() on the job.

Output:

com.example.kotlincoroutines I / System . out : 86
com.example.kotlincoroutines I / System . out : 87
com.example.kotlincoroutines I / System . out : 88
com.example.kotlincoroutines I / System . out : 89
com.example.kotlincoroutines I / System . out : 90
com.example.kotlincoroutines D / Exception : Timed out waiting for 2000 ms handled !
com.example.kotlincoroutines D / finally : clear all resources

Timeout on Kotlin Coroutine

Are you want to cancel the particular operation, if it takes a long time to complete in kotlin coroutines? Then you need
to run the operation with withTimeout(timeInMilliseconds) function inside the coroutine scope. This will cancel the
operation automatically after the defined time is reached.

fun startPrintWithTimeout() {

    viewModelScope.launch {
        try {
            withTimeout(2000) {
                for (i in 1..1000) {
                    delay(20)
                    println(i)
                }
            }
        } catch (e: Exception) {
            Log.d("Exception", "${e.message.toString()} handled !")
        } finally {
            Log.d("finally", "clear all resources")
        }
    }
}

In the above code, I am printing 1 to 1000 numbers in a 20-milliseconds delay inside the ViewModelScope. Also, I have
surrounded the printing operation with the withTimeOut(2000) function. So, the printing operation will be canceled
after 2000 milliseconds. Also, the printing operation is surrounded by a try/catch block. So the canceled operation with
be caught.

Output:

com.example.kotlincoroutines I / System . out : 71
com.example.kotlincoroutines I / System . out : 72
com.example.kotlincoroutines I / System . out : 73
com.example.kotlincoroutines I / System . out : 74
com.example.kotlincoroutines D / Exception : Timed out waiting for 2000 ms handled !
com.example.kotlincoroutines D / finally : clear all resources

you can download this example on Github.

What’s Next:

Kotlin High Order Functions and Lambdas Explained

Kotlin Scope Functions Explained [Example]

koin – Dependency Injection In Android

Conclusion

I hope you learned about the kotlin coroutine and how to handle the exception and cancel the kotlin Coroutine. let me
know your feedback in the comments.


Comments

Leave a Reply

Your email address will not be published. Required fields are marked *


Latest Posts