In scenarios requiring periodic code execution, Android relies on the java.util.Timer and java.util.TimerTask classes. TimerTask defines the payload, while Timer controls the schedule.
Understanding TimerTask
The TimerTask class must be subclassed, and its run() method provides the entry point for the background work. The class itself is abstract and cannot be instantiated directly.
public abstract class TimerTask {
// ...
}
Create a custom task by overriding run:
class HeartbeatTask extends TimerTask {
@Override
public void run() {
sendKeepAliveSignal();
}
private void sendKeepAliveSignal() {
// network call here
}
}
Using the Timer Scheduler
A Timer instance manages a queue of tasks. Call schedule(TimerTask task, long delay, long period) to execute a task after an initial wait and then repeatedly at a fixed interval.
Timer scheduler = new Timer();
HeartbeatTask beat = new HeartbeatTask();
// Fire after 2 seconds, then every 5 seconds
scheduler.schedule(beat, 2000L, 5000L);
The first argument is the task object, the second is the initial delay in milliseconds (0 means immediately), and the third is the subsequent interval. Other overloads support one‑shot execution or scheduling at a specific Date.
Complete Illustration
The program below prints the current timestamp every second, starting immediately.
import java.time.LocalTime;
import java.util.Timer;
import java.util.TimerTask;
public class PeriodicLogger {
public static void main(String[] args) {
TimerTask logTask = new TimerTask() {
@Override
public void run() {
System.out.println("Tick at " + LocalTime.now());
}
};
Timer timer = new Timer(true); // daemon thread
timer.schedule(logTask, 0L, 1000L);
// Simulate running environment
try {
Thread.sleep(10_000L);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
timer.cancel(); // clean shutdown
}
}
Important Notes
- The
run()method executes on a background thread, so direct UI updates will fail. UserunOnUiThreador aHandlerto post results back to the main thread. Timeruses a single thread internally; long‑running tasks can delay subsequent scheduled executions. For concurrent or complex scheduling, considerScheduledExecutorService.- Always call
cancel()on both theTimerand pendingTimerTaskobjects when the activity or the component is destroyed to avoid memory leaks.