'How can I execute cleanup code in my CoroutineWorker when onStopped is final?
I upgraded to WorkManager 2.1.0 and tried to use some of the Kotlin extensions including CoroutineWorker
. My worker was extending androidx.work.Worker
previously and it was executing cleanup code by overriding onStopped
. Why is onStopped
final in CoroutineWorker
? Is there any other way for me to execute cleanup code after the CoroutineWorker
is stopped?
According to this blog post, is this supposed to be a feature?
Solution 1:[1]
You can always use job.invokeOnCompletetion
without having to rely in the onStopped
callback for CoroutineWorker
. For e.g.
import android.content.Context
import android.util.Log
import androidx.work.CoroutineWorker
import androidx.work.WorkerParameters
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.async
import kotlinx.coroutines.coroutineScope
class TestWorker(context: Context, params: WorkerParameters) : CoroutineWorker(context, params) {
companion object {
private const val TAG = "TestWorker"
}
override suspend fun doWork(): Result {
return coroutineScope {
val job = async {
someWork()
}
job.invokeOnCompletion { exception: Throwable? ->
when(exception) {
is CancellationException -> {
Log.e(TAG, "Cleanup on completion", exception)
// cleanup on cancellations
}
else -> {
// do something else.
}
}
}
job.await()
}
}
suspend fun someWork(): Result {
TODO()
}
}
Solution 2:[2]
From Kotlin documentation:
Cancellable suspending functions throw CancellationException on cancellation which can be handled in the usual way. For example, try {...} finally {...} expression and Kotlin use function execute their finalization actions normally when a coroutine is cancelled. Coroutines documentation
That means that you can clean up coroutine code in usual, Java/Kotlin way with try and finally:
override suspend fun doWork(): Result {
return try {
work()
Result.success()
} catch (e: Exception) {
Result.failure()
} finally {
cleanup()
}
}
Note that you can't suspend in catch and finally. If you do, use withContext(NonCancellable) NonCancellable documentation
Solution 3:[3]
Just catch CancellationException
override suspend fun doWork(): Result {
return try {
// here do work
return Result.success()
} catch (e: CancellationException) {
// here clean up
return Result.failure()
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Rahul |
Solution 2 | Michal Engel |
Solution 3 | Vlad |