How to remove a runnable from a handler object added by postDelayed?

AndroidHandlerRunnablePostdelayed

Android Problem Overview


I have an "open" animation and am using Handler.postDelayed(Runnable, delay) to trigger a "close" animation after a short delay. However, during the time between open and close, there is possibly another animation triggered by a click.

My question is, how would I cancel the "close" animation in the handler?

Android Solutions


Solution 1 - Android

Just use the removeCallbacks(Runnable r) method.

Solution 2 - Android

Cristian's answer is correct, but as opposed to what is stated in the answer's comments, you actually can remove callbacks for anonymous Runnables by calling removeCallbacksAndMessages(null);

As stated here:

> Remove any pending posts of callbacks and sent messages whose obj is token. If token is null, all callbacks and messages will be removed.

Solution 3 - Android

This is a late answer, but here's a different method for when you only want to remove a specific category of runnables from the handler (i.e. in OP's case, just remove the close animation, leaving other runnables in the queue):

    int firstToken = 5;
    int secondToken = 6;

    //r1 to r4 are all different instances or implementations of Runnable.  
    mHandler.postAtTime(r1, firstToken, 0);
    mHandler.postAtTime(r2, firstToken, 0);
    mHandler.postAtTime(r3, secondToken, 0);

    mHandler.removeCallbacksAndMessages(firstToken);

    mHandler.postAtTime(r4, firstToken, 0);

The above code will execute "r3" and then "r4" only. This lets you remove a specific category of runnables defined by your token, without needing to hold any references to the runnables themselves.

Note: the source code compares tokens using the "==" operand only (it does not call .equals()), so best to use ints/Integers instead of strings for the token.

Solution 4 - Android

If your using recursion, you can acheive this by passing "this". See code below.

public void countDown(final int c){
    mHandler.postDelayed(new Runnable() {
        @Override
        public void run() {
        	aq.id(R.id.timer).text((c-1)+"");
        	if(c <= 1){
        		aq.id(R.id.timer).gone();
        		mHandler.removeCallbacks(this);
        	}else{
        		countDown(c-1);
        	}
        }
    }, 1000);
}

This example will set the text of a TextView (timer) every second, counting down. Once it gets to 0, it will remove the the TextView from the UI and disable the countdown. This is only useful for someone who is using recursion, but I arrived here searching for that, so I'm posting my results.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionBruce LeeView Question on Stackoverflow
Solution 1 - AndroidCristianView Answer on Stackoverflow
Solution 2 - AndroidDaniel L.View Answer on Stackoverflow
Solution 3 - AndroidNameSpaceView Answer on Stackoverflow
Solution 4 - AndroidrobisaksView Answer on Stackoverflow