Kotlin unable to stop handler running

Issue

I am running a handler that updates a textView element. The handler is started and stopped at the click of a button but once I start it, I cannot stop it.

fun updateTextView(handler: Handler, run: Boolean = true) {
    val runnable: Runnable = object : Runnable {
        override fun run() {
            // update text view element
            handler.postDelayed(this, 500)
        }
    }
    if (run) handler.postDelayed(runnable, 500)
    // this should stop it?
    else handler.removeCallbacks(runnable)
}

And my function to detect clicks

val textHandler = Handler(Looper.getMainLooper())

private fun setupClickListeners() {
    startLive.setOnClickListener{
        updateTextView(textHandler)
    }

    stopLive.setOnClickListener{
        updateTextView(textHandler, run = false)
    }
}

Solution

This is a general way to do what you need:

// store an instance of your runnable task
val runnable: Runnable = object : Runnable {
    override fun run() {
        // update text view element
        handler.postDelayed(this, 500)
    }
}

fun startRunnable() {
    // you could just run it to get it going, since it posts itself
    runnable.run()
}

fun stopRunnable() {
    // remove this specific instance from the message queue
    handler.removeCallbacks(runnable)
}

Like I said in the comment, your version is creating a new Runnable instance every time you run the function – then after posting it to the queue, it immediately removes it again. If you didn’t remove it, it would run – but you wouldn’t be able to stop it, because you don’t have a stored reference to the instance you created, so you can’t pass it to removeCallbacks. (Running the function again like you’re doing just creates a new Runnable, so cancelling that won’t affect the other one.)

By storing the Runnable as a variable, you have access to it – so you can easily pass it to removeCallbacks, and reuse it by posting it again. This doesn’t work if you actually need multiple instances (like you have separate tasks going on) – in that case, you’d need to store references to each Runnable you create, and have some way to coordinate which one you’re cancelling

Answered By – cactustictacs

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published