Reputation: 811
I'm trying to run some long running task in coroutine. Sometimes i need to cancel this coroutine, but after job.cancel()
it still continues to work.
Here is some code demonstration similar to my real code:
class TestActivity : AppCompatActivity()
{
val job = Job()
override fun onCreate(savedInstanceState: Bundle?)
{
super.onCreate(savedInstanceState)
lifecycleScope.launch(Dispatchers.IO + job, block =
{
for (i in 0..100)
{
Log.e("TestActivity", "Time passed = ${i * 100}")
Thread.sleep(100)
}
Log.e("TestActivity", "Code after cycle")
})
Handler().postDelayed(
{
Log.e("TestActivity", "**** Trying to cancel job ****")
job.cancel()
}, 3000)
}
}
In my logcat i get logs after cancelling job.
...
TestActivity: Time passed = 2300
TestActivity: Time passed = 2400
TestActivity: **** Trying to cancel job ****
TestActivity: Time passed = 2500
TestActivity: Time passed = 2600
...
TestActivity: Code after cycle
What is the proper way to cancel such tasks?
Upvotes: 1
Views: 535
Reputation: 3745
You have to make your coroutines cooperative with cancellation. If you make use of any suspending function from kotlinx.coroutines
then it's already cooperative with cancellation. For example instead of Thread.sleep
use delay
:
...
for (i in 0..100)
{
Log.e("TestActivity", "Time passed = ${i * 100}")
delay(100)
}
...
When you have a heavy task and you're not calling a suspending function from kotlinx.coroutines
, you can check its isActive
property when necessary which will be false
if the coroutine is cancelled:
...
for (i in 0..100)
{
if(!isActive)
break;
...
}
...
Upvotes: 4