Question
How can I call a Java method in an Android app after a specified delay? In Objective-C, I could use performSelector:withObject:afterDelay::
[self performSelector:@selector(doSomething) withObject:nil afterDelay:5];
What is the Android Java equivalent if I need to call a method such as doSomething() after five seconds?
public void doSomething() {
// Do something here.
}
Short Answer
You will learn how to schedule code to run later in an Android Java app with Handler.postDelayed(). You will also learn why delayed work is usually posted to the main thread, how to cancel it, and how to avoid updating a screen after its Activity has been destroyed.
Concept
Android does not use Objective-C's performSelector:withObject:afterDelay: API. In Java-based Android apps, a common equivalent is a Handler and its postDelayed() method.
A Handler places a Runnable—a piece of code to run—onto a thread's message queue. postDelayed() adds that work to the queue but tells Android not to run it until the requested delay has passed.
For UI-related work, create the handler with Looper.getMainLooper(). This posts the work to Android's main thread, which is the thread allowed to update views such as TextView, Button, and RecyclerView.
Handler handler = new Handler(Looper.getMainLooper());
handler.postDelayed(() -> doSomething(), 5_000);
The delay is measured in milliseconds, so 5_000 means five seconds.
A delay is not a guarantee of exact timing. Android will run the task no earlier than the requested delay when the target thread is able to process it. If the main thread is busy, the callback can happen later.
Mental Model
Think of a Handler as a receptionist with a timed appointment book.
- A
Runnableis an instruction card: “rundoSomething().” postDelayed()gives the receptionist the card and says: “do not hand this to the main thread for 5 seconds.”- After the time passes, the main thread receives the card when it is free.
removeCallbacks()takes the card back before it is delivered.
This is useful when an action should happen later, but you may no longer need it if the user leaves the screen.
Syntax and Examples
Create a Handler for the main thread, then post a Runnable with a delay in milliseconds.
import android.os.Handler;
import android.os.Looper;
Handler handler = new Handler(Looper.getMainLooper());
handler.postDelayed(new Runnable() {
@Override
public void run() {
doSomething();
}
}, 5_000);
With Java 8 language support enabled in an Android project, the same code can be shorter with a lambda:
handler.postDelayed(() -> doSomething(), 5_000);
For example, this changes a message after two seconds:
TextView statusText = findViewById(R.id.status_text);
Handler handler = new Handler(Looper.getMainLooper());
statusText.setText("Waiting...");
handler.postDelayed(() -> {
statusText.setText("Finished");
}, );
Step by Step Execution
Consider this code:
Handler handler = new Handler(Looper.getMainLooper());
handler.postDelayed(() -> {
doSomething();
}, 5_000);
new Handler(Looper.getMainLooper())creates a handler associated with the UI thread.postDelayed(...)receives the lambda and the delay value5_000.- Android adds the lambda to the main thread's message queue with a future execution time.
- The current method continues immediately; it does not pause for five seconds.
- After at least five seconds, Android checks the main thread's queue.
- When the main thread is available, it runs the lambda.
- The lambda calls
doSomething().
private void doSomething() {
Log.d("DelayExample", "Five seconds have passed");
}
If the UI thread is blocked by expensive work, step 6 occurs later. Keep UI-thread callbacks short.
Real World Use Cases
Delayed callbacks are useful for small, UI-oriented tasks such as:
- Splash or onboarding transitions: show an introductory message briefly before revealing the next screen.
- Search input debouncing: wait briefly after the user stops typing before requesting search results.
- Temporary feedback: hide a success message or undo bar after a few seconds.
- Button protection: re-enable a button after a short cooldown.
- Animations and UI sequencing: start a second UI change after the first one has had time to appear.
- Retry timing: schedule a lightweight retry after a short wait, while still considering lifecycle and network requirements.
For work that must continue reliably after the user closes the app or after a device restart, a simple Handler is usually not the correct tool. Use an Android scheduling API designed for persistent background work, such as WorkManager, when appropriate.
Real Codebase Usage
In production code, developers usually keep a reference to the delayed Runnable. This makes cancellation possible and prevents an old screen from being updated later.
private final Handler handler = new Handler(Looper.getMainLooper());
private final Runnable showResultRunnable = () -> {
showResult();
};
private void scheduleResult() {
handler.postDelayed(showResultRunnable, 5_000);
}
private void cancelScheduledResult() {
handler.removeCallbacks(showResultRunnable);
}
A common Activity pattern is to cancel callbacks when the activity is being destroyed:
@Override
protected void onDestroy() {
handler.removeCallbacks(showResultRunnable);
super.onDestroy();
}
For a search field, cancel the previous request before scheduling a new one. This is a debounce pattern:
Common Mistakes
Treating seconds as milliseconds
postDelayed() expects milliseconds.
// Wrong: this delays for 5 milliseconds, not 5 seconds.
handler.postDelayed(() -> doSomething(), 5);
// Correct
handler.postDelayed(() -> doSomething(), 5_000);
Blocking the main thread with Thread.sleep()
// Wrong when called on the Android UI thread.
Thread.sleep(5_000);
doSomething();
This freezes the UI for five seconds. Schedule the callback instead:
handler.postDelayed(() -> doSomething(), 5_000);
Updating a view from a background thread
Android views must be changed on the main thread. If code is running on a background executor, use a main-thread handler for the UI update:
new Handler(Looper.getMainLooper()).postDelayed(() -> {
statusText.setText("Done");
}, 5_000);
Forgetting to cancel an outdated callback
A user may leave the screen before the delay ends. If the callback uses that screen's views, cancel it during the appropriate lifecycle event:
Comparisons
| Approach | Best for | Important behavior |
|---|---|---|
Handler.postDelayed() | Short UI delays and main-thread callbacks | Runs on the handler's looper; can be cancelled with removeCallbacks() |
View.postDelayed() | A delay directly associated with one view | Convenient for view-related code; still cancel or account for lifecycle when needed |
Thread.sleep() | Pausing a background thread only | Blocks that thread; never sleep on the UI thread |
Timer / TimerTask | Older Java timer-style code | Usually less convenient for Android UI work because UI updates still need the main thread |
| WorkManager | Deferrable background work that should survive app exits | Not intended for an exact five-second UI delay |
Cheat Sheet
// Imports
import android.os.Handler;
import android.os.Looper;
// Main-thread handler
Handler handler = new Handler(Looper.getMainLooper());
// Run once after 5 seconds
handler.postDelayed(() -> doSomething(), 5_000);
// Keep a Runnable reference when it may need cancellation
Runnable task = () -> doSomething();
handler.postDelayed(task, 5_000);
// Cancel that pending task
handler.removeCallbacks(task);
postDelayed(runnable, delayMillis)uses milliseconds.1_000ms = 1 second.- A main-looper handler can safely update Android views.
- The calling method continues immediately after scheduling.
- Delays can run late if the target thread is busy.
- Cancel callbacks that are no longer valid, especially when a screen is closed.
- Do not call
Thread.sleep()on the main thread.
FAQ
What is the Android Java equivalent of performSelector:afterDelay:?
For common UI work, use Handler.postDelayed() with a Runnable:
new Handler(Looper.getMainLooper()).postDelayed(() -> doSomething(), 5_000);
Is the delay value in seconds?
No. postDelayed() uses milliseconds. Use 5_000 for five seconds.
Does postDelayed() block the current method?
No. It schedules work for later and returns immediately.
Can I update a TextView in a delayed callback?
Yes, when the callback is posted through a handler associated with Looper.getMainLooper() or through view.postDelayed().
How do I cancel a delayed method call in Android?
Keep the same Runnable instance and pass it to removeCallbacks():
handler.removeCallbacks(task);
Mini Project
Description
Build a small delayed status screen. When the user taps a button, the app shows a waiting message and schedules a completion message for five seconds later. If the activity is destroyed before the delay ends, the pending callback is cancelled.
Goal
Use Handler.postDelayed() to update an Android TextView after five seconds without blocking the UI.
Requirements
Create an activity with a status TextView and a start Button.
Keep learning
Related questions
Add External JAR Files to an IntelliJ IDEA Java Project
Learn how to add external JAR dependencies to an IntelliJ IDEA Java project using module libraries, and when to use Maven or Gradle instead.
Avoiding Java Code in JSP with JSP 2: EL and JSTL Explained
Learn how to avoid Java scriptlets in JSP 2 using Expression Language and JSTL, with examples, best practices, and common mistakes.
Choosing a @NotNull Annotation in Java: Validation vs Static Analysis
Learn how Java @NotNull annotations differ, when to use each one, and how to choose between validation, IDE hints, and static analysis tools.