113

Let's say that I want to perform some action every 10 seconds and it doesn't necessarily need to update the view.

The question is: is it better (I mean more efficient and effective) to use timer with timertask like here:

final Handler handler = new Handler(); TimerTask timertask = new TimerTask() { @Override public void run() { handler.post(new Runnable() { public void run() { <some task> } }); } }; timer = new Timer(); timer.schedule(timertask, 0, 15000); } 

or just a handler with postdelayed

final Handler handler = new Handler(); final Runnable r = new Runnable() { public void run() { <some task> } }; handler.postDelayed(r, 15000); 

Also I would be grateful if you could explain when to use which approach and why one of them is more efficient than another (if it actually is).

7
  • 2
    I've read many posts about irregular behavior of TimerTasks. My advice would be steer clear of them and use the handler / postDelayed approach. Commented Dec 2, 2013 at 14:18
  • 1
    I'd prefer the Handler-postDelay method - you have more control and you schedule it from the inside Commented Dec 2, 2013 at 14:27
  • 1
    Here is a great source for Timer vs. Handler Commented Jan 13, 2015 at 14:20
  • TimerTask is a background-task, so you can not update UI. Just saying... Commented Mar 16, 2016 at 1:29
  • For the people reading this: @Yousha Aleayoub of course you can using the Handler. Commented Oct 15, 2019 at 13:33

3 Answers 3

113

Handler is better than TimerTask.

The Java TimerTask and the Android Handler both allow you to schedule delayed and repeated tasks on background threads. However, the literature overwhelmingly recommends using Handler over TimerTask in Android (see here, here, here, here, here, and here).

Some of reported problems with TimerTask include:

  • Can't update the UI thread
  • Memory leaks
  • Unreliable (doesn't always work)
  • Long running tasks can interfere with the next scheduled event

Example

The best source for all kinds of Android examples that I have seen is at Codepath. Here is a Handler example from there for a repeating task.

// Create the Handler object (on the main thread by default) Handler handler = new Handler(); // Define the code block to be executed private Runnable runnableCode = new Runnable() { @Override public void run() { // Do something here on the main thread Log.d("Handlers", "Called on main thread"); // Repeat this the same runnable code block again another 2 seconds handler.postDelayed(runnableCode, 2000); } }; // Start the initial runnable task by posting through the handler handler.post(runnableCode); 

Related

Sign up to request clarification or add additional context in comments.

11 Comments

@Reek No, GC should take care of it. But you need to take care of the runnable posted for delayed execution. In the example above the runnable used is an inner class instance so holds an implicit reference to the containing class (which might be an activity). The runnable will stay in the handler's associated looper's message queue until its next execution time which may be after the context is invalid and might leak the containing class instance. You can clear such references by using mHandler.removeCallbacks(runnableCode) at the appropriate time (e.g. onStop() for an activity).
Best way of presenting references ever!!! (see here, here, here, here, here, and here).
and what if I want to use that inside a ViewModel? isn't against the ideal of not having android things there?
@desgraci, I haven't used a ViewModel, but from the documentation I only see that it says the ViewModel shouldn't access the view hierarchy or contain a reference to the Activity or Fragment. I don't see anything forbidding having "Android things" in general.
As of today those references are to me outdated and not informative enough to be taken into consideration. Those 4 listed drawbacks are only real if you programm your code badly. TimerTasks are still a very good choice if you want to periodically run something in the background and eventually run something on the UIThread if some condition applies.
|
19

There are some disadvantages of using Timer

It creates only single thread to execute the tasks and if a task takes too long to run, other tasks suffer. It does not handle exceptions thrown by tasks and thread just terminates, which affects other scheduled tasks and they are never run

Copied from:

TimerTask vs Thread.sleep vs Handler postDelayed - most accurate to call function every N milliseconds?

2 Comments

so what about for a one-shot task? it sounds like maybe Timer is better for that because you don't have the overhead of the message queue?
I guess we'll never know
12

Kotlin version of accepted answer:

// execute on the main thread, empty constructor is deprecated val handler = Handler(Looper.getMainLooper()) val runnableCode = object : Runnable { override fun run() { Log.d("Handlers", "Called on main thread") handler.postDelayed(this, 2000) } } // or shorter using a lambda function val runnableCode = Runnable { Log.d("Handlers", "Called on main thread") handler.postDelayed(this, 2000) } handler.post(runnableCode) 

1 Comment

Would be helpful to add an example of a Handler running on a separate thread, for tasks that do not need to update ui.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.