androidfunctionkotlincountersuspend

cancelling a suspend function in kotlin if the same function is called again


I want to cancel the function i created which simply increments a counter value. For example, if the specific function is triggered by click, I only want to display the log for the last uninterrupted click within 2 seconds. Basically, i want the function to cancel itself if called again if its ongoing (delay is ongoing). Is there such thing in kotlin?

val counter = mutableStateOf(0)
suspend fun addCounter(){
    counter.value++
    
   
    delay(2000)
    Log.e("click cat","click $counter")
}`

Solution

  • This kind of event processing is usually handled using reactive streams and is often named the debounce operator. It exists in both ReactiveX (Debounce) and in Kotlin flows (debounce()).

    As you already use coroutines, I suggest going with Kotlin flows. Please see the example below:

    private val flow = MutableStateFlow(0)
    
    suspend fun main() = coroutineScope {
        launch {
            // consumer of events
            flow
                .debounce(2.seconds)
                .collect { println(it) }
        }
    
        // producer
        delay(100)
        addCounter() // 1
        delay(500)
        addCounter() // 2, ignore 1
        delay(500)
        addCounter() // 3, ignore 2
        delay(2500) // show 3
        addCounter() // 4
        delay(500)
        addCounter() // 5, ignore 4
        delay(3000) // show 5
    }
    
    fun addCounter() {
        flow.value++
    }
    

    It shows only 3 and 5, because all other events were "cancelled" by subsequent events that came too fast.