Wake me in X milliseconds

This note illustrates an important technique in Android, for calling a method (on the UI thread) after a short delay. You can use this to update the UI periodically, even when the user is not clicking anything.

To get started, you will need a Handler object as an instance variable in your activity class:

    Handler handler = new Handler();

If you need to import it manually:

import android.os.Handler

The Handler method we’ll use here is called postDelayed. It takes a Runnable object (which is just anything with a run method), and an integer number of milliseconds.

Here’s a simple “count-down” example you can incorporate into a hello-world activity with a TextView:

    final int INTERVAL = 1000; // milliseconds = 1 second
    int timeRemaining = 20;
    TextView textView;
    Handler handler = new Handler();

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        textView = (TextView) findViewById(R.id.textView);
        textView.setText(""+timeRemaining);
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                timeRemaining--;
                textView.setText(""+timeRemaining);
                if(timeRemaining > 0) {
                    handler.postDelayed(this, INTERVAL);
                }
            }
        }, INTERVAL);
    }

When the activity opens, it shows the number 20, but then it counts down to zero, one number per second. Notice how postDelayed is called from within onCreate, but then again nested within the run method – as long as the timeRemaining is not yet zero.

One moment in the countdown

One moment in the countdown

I try to avoid the nested anonymous class syntax whenever possible – that’s where it says new Runnable() {…}. A cleaner way is to make the activity itself runnable. That would look like this:

package com.example.countdown;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.widget.TextView;

public class CountdownActivity extends Activity implements Runnable {
    final int INTERVAL = 1000; // milliseconds = 1 second
    int timeRemaining = 20;
    TextView textView;
    Handler handler = new Handler();

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        textView = (TextView) findViewById(R.id.textView);
        textView.setText(""+timeRemaining);
        handler.postDelayed(this, INTERVAL);
    }

    @Override
    public void run() {
        timeRemaining--;
        textView.setText("" + timeRemaining);
        if (timeRemaining > 0) {
            handler.postDelayed(this, INTERVAL);
        }
    }
}

Using this technique, I managed to make the rabbit-pellet game so that I don’t have to hit the arrow buttons hundreds of times. Instead, I just hold it down and the rabbit keeps moving. In this program, the delay interval is 50 milliseconds (20 times per second).