Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to cancel old coroutine when new one is called on same thread

Currently I have this block of code.

If the user stays on the same Fragment, I get the apiGetObject from an API and I want to renew that with the resetTime - current ( note that this value will consistently be 3 minutes ).

This code delay the needReload.value = true for that amount of time.

GlobalScope.launch(Dispatchers.Main) {
    apiGetObject.value?.resetTime?.let {
        if (it - System.currentTimeMillis() > 0) {
            delay(it - System.currentTimeMillis())
        }
    }
    needReload.value = true
}

Now I retrieve the object on every onResume to refresh the data ( this is a must ). So if the Fragment is resumed under the 3 minutes window, another coroutine will be launched.

=> This makes the data

What I want:

I want if there is a new coroutine launch then the previous one is cancelled/destroy. Is there anyway to do this ( other solutions that this coroutine is welcome )

Note: Im using MVVM with LiveData and I get the apiGetObject with Retrofit and RX

like image 511
adam yong Avatar asked Mar 04 '23 16:03

adam yong


1 Answers

For canceling a coroutine, you can keep the reference of the 'Job' Object returned while launching the coroutine and when you want to stop that coroutine you can call 'job.cancel()'

In your case,

First create a global variable for job

var job : Job? = null

and when you are launching your coroutine

job?.cancel()

job = GlobalScope.launch(Dispatchers.Main) {
    apiGetObject.value?.resetTime?.let {
        if (it - System.currentTimeMillis() > 0) {
            delay(it - System.currentTimeMillis())
        }
    }
    needReload.value = true
}

So here before starting a coroutine, we are cancelling the previous one if it exists.

like image 124
Pavan Varma Avatar answered Apr 27 '23 04:04

Pavan Varma