What do I use now that Handler() is deprecated?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
On Android, Handler itself is not deprecated. What is deprecated is the implicit constructor style such as new Handler() and new Handler(callback), because those forms silently pick the current thread's Looper and can attach your handler to the wrong thread or to no valid looper at all.
What Changed
The Android docs deprecate the zero-argument and callback-only constructors because implicit thread-local looper selection is error-prone. The modern fix is to make the looper explicit or use a higher-level concurrency tool that better matches the job.
In other words, replace this:
with something explicit like this:
That one change already removes most of the ambiguity.
Posting Work to the Main Thread
If your goal is "run this on the UI thread," the modern direct replacement is an explicit main looper handler.
This is still valid Android code. The key improvement is that the target thread is obvious.
Sometimes You Do Not Need Handler at All
Many older code samples used Handler as a generic async tool even when a better abstraction existed. If you are doing background work, prefer APIs that express background execution directly:
- '
ExecutororExecutorServicefor Java concurrency' - Kotlin coroutines for modern Kotlin apps
- '
WorkManagerfor guaranteed deferrable background work'
For example, this is often clearer than a background HandlerThread for one-off tasks:
When Handler Is Still the Right Tool
Handler still makes sense when you are interacting with an existing Looper and message queue. Typical examples include:
- posting back to the main thread
- interoperating with APIs that already use
Messageobjects - working on a dedicated looper thread
If you truly need a handler on a non-main looper, create or obtain that looper explicitly.
This is much clearer than relying on implicit construction.
View and Activity Helpers Can Be Simpler
If the job is tied to a UI element, helper APIs may be better than managing a raw handler yourself.
Or in an Activity:
These helpers communicate intent directly and avoid manual looper plumbing.
Async Handlers
If you need a handler whose messages are not blocked by synchronization barriers such as display vsync, Android also offers async handler creation.
That is a specialized tool, not a general replacement for every handler use case, but it is worth knowing when UI scheduling behavior matters.
Common Pitfalls
The biggest pitfall is thinking Handler has been deprecated entirely. It has not. The problem is the implicit constructor style, not the entire class.
Another issue is replacing every Handler with an executor without checking whether the code actually needs a looper-backed message queue. Executors run tasks, but they are not message-loop primitives.
Developers also keep using new Handler() in utility code that may run on threads without loopers. That is exactly the kind of fragile behavior the deprecation was meant to surface.
Finally, do not use Handler as a blanket answer for long-running or guaranteed background work. For that, WorkManager or other lifecycle-aware tools are often more appropriate.
Summary
- '
Handleris still valid; only the implicit constructors such asnew Handler()are deprecated.' - Use
new Handler(Looper.getMainLooper())when you need to post to the UI thread. - Use
HandlerThreadplus an explicit looper only when you truly need a looper-backed worker thread. - Prefer executors, coroutines, or
WorkManagerwhen the problem is general concurrency rather than message-loop scheduling. - Make the target thread explicit so the code is predictable and easier to maintain.

