How do I stop a Kotlin coroutine on Android?

Viewed 7765

I am trying to stop a coroutine if user presses a button. However, when I do:

GlobalScope.launch(Dispatchers.Main) {
     //code
}

button.setonclicklistener(){
    GlobalScope.cancel()
}

The app crashes. How can I fix this?

3 Answers

Change it like this

var job: Job? = null


job = GlobalScope.launch(Dispatchers.Main) {
    //code
}

button.setonclicklistener(){
    job?.cancel()
}

Here is the sample you can use and modify as per your code

val job =GlobalScope.launch(Dispatchers.Main) {
    try {
       //code
    } finally {
        println("job: I'm running finally")
    }
}
job.cancelAndJoin() // cancels the job and waits for its completion
println("main: Now I can quit.")

First, I would like to point out that you should not use the GlobalScope. Instead, you should make your local scope bound to your component fragment/activity/presenter, etc. lifecycle. here's why https://elizarov.medium.com/the-reason-to-avoid-globalscope-835337445abc

Now, once that is taken care of, you can create a local scope like this (assuming you need MainScope)

class MyFragment: Fragment(), CoroutineScope by MainScope() {
    var job: Job? = null
    ....

Next, like @Francesc suggested, you'll need to grab a Job reference. Since every coroutine launch returns a Job, you can keep the reference and cancel it whenever you need. Or in this case, if the fragment dies, the coroutine will be canceled automatically as it's bound to the fragment now (which is most of the time the desired behavior).

job = launch {
    // your code
}

button.setOnClickListener() {
    job?.cancel()
}

Also please note that now you don't have to mention the scope and context before launching.

Related