Recently, I've upgraded Kotlin Coroutines from experimental to 1.1.1 and faced the problem that job.cancel() in new version works differently.
Here's the code with Experimental Coroutines:
fun <R : Any, T : Deferred<R>> T.runAsync(
job: Job,
onSuccess: (result: R) -> Unit,
onFailed: (errorMsg: String?) -> Unit) {
launch(UI, parent = job) {
try {
val result = [email protected]()
onSuccess(result)
} catch (e: Exception) {
onFailed(e.message)
}
}
}
Here's with 1.1.1:
fun <R : Any, T : Deferred<R>> T.runAsync(
job: Job,
onSuccess: (result: R) -> Unit,
onFailed: (errorMsg: String?) -> Unit) {
GlobalScope.launch(Dispatchers.Main + job) {
try {
val result = withContext(Dispatchers.IO) {
[email protected]()
}
onSuccess(result)
} catch (e: Exception) {
onFailed(e.message)
}
}
}
For example:
My fragment destroyed and called job.cancel() during coroutine is running.
In experimental coroutines neither onSuccess() nor onFailed() will be called.
In 1.1.1: onFailed() called because caught of JobCancellationException
I figured out to add catch (e: JobCancellationException), but it's impossible:
/**
* @suppress **This an internal API and should not be used from general code.**
*/
internal expect class JobCancellationException(
So, the question is: How to handle/ignore JobCancellationException ?
You try to catch the super-class
CancellationExceptioninstead, which is a part of the public API.Do note that if something throws
CancellationExceptionyou are generally expected to rethrow it so upstream objects are notified about the cancellation. See Cancellation is Cooperative