Reputation: 33
I tried to run two async jobs.
There is a button when clicked, would cancel one of the jobs. But I noticed when I do it, the other job will be cancelled too.
What happened?
class SplashFragment : BaseFragment(R.layout.fragment_splash), CoroutineScope by MainScope() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
launch {
val countdown = async { countDown() }
val ipAndMaintain = async { checkIPAndMaintain() }
btnSkip.onClick {
countdown.cancel() // cancel countdown
btnSkip.isVisible = false
if (!ipAndMaintain.isCompleted) {
showLoadingDialog()
}
}
countdown.await()
startOtherPage(ipAndMaintain.await())
}
}
private suspend fun countDown() {
var time = 3
while (time >= 0) {
btnSkip.text = getString(R.string.skip, time)
delay(1000)
yield()
time--
}
}
private suspend fun checkIPAndMaintain(): Int {
delay(2000)
return 1
}
}
Upvotes: 3
Views: 914
Reputation: 3745
When you call await
on a cancelled Deferred
it throws an Exception. If you don't catch it then it will be propagated to the parent coroutine which will cancel all its children. Wrap your countdown.await()
instruction with a try-catch
block and you'll see that the other coroutine continues. That's the effect of structured concurrency.
You can read this article by Roman Elizarov about the topic.
Upvotes: 6