Timertask or Handler
Solution 1
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
Solution 2
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:
Solution 3
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)
Related videos on Youtube
keysersoze
Updated on July 08, 2022Comments
-
keysersoze almost 2 years
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).
-
Sound Conception over 10 yearsI've read many posts about irregular behavior of TimerTasks. My advice would be steer clear of them and use the handler / postDelayed approach.
-
mihail over 10 yearsI'd prefer the Handler-postDelay method - you have more control and you schedule it from the inside
-
CodyF over 9 yearsHere is a great source for Timer vs. Handler
-
Yousha Aleayoub about 8 yearsTimerTask is a background-task, so you can not update UI. Just saying...
-
David over 4 yearsFor the people reading this: @Yousha Aleayoub of course you can using the Handler.
-
Yousha Aleayoub over 4 years@David I'm talking about
TimerTask
notHandler
. -
David over 4 years@Yousha Aleayoub I know, but if you want something to run in the backgronud you will use TimerTask and then to update the UI from inside the TimerTask you will use the handler to do this. With Handler you run directly all in the UI Thread which will not always be what you want.
-
-
Michael almost 10 yearsso 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?
-
bitbybit almost 7 years@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). -
Dunes Buggy over 6 yearsBest way of presenting references ever!!! (see here, here, here, here, here, and here).
-
Denny over 5 yearsI guess we'll never know
-
desgraci about 5 yearsand what if I want to use that inside a ViewModel? isn't against the ideal of not having android things there?
-
Suragch about 5 years@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.
-
David over 4 yearsAs 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.
-
David over 4 years"But you need to take care of the runnable posted for delayed execution" to solve this you need to create a static class thtat implements Runnable and save a weekReference of the containing class (perhaps the actiivity), doing so you would solve the problem of eventual memory leak.
-
Suragch over 4 years@David, thanks for your comments. Is there any reason you wouldn't use a
Handler
? IfTimerTask
is susceptible to people who program badly, then I still prefer to avoid it. I tend to program badly on occasion. -
David over 4 yearsHandler is also equally susceptible being able to produce memory leaks on Android if not programmed carefully enough. I don't think one is better than the other, it depends on the case.
-
Joxon over 4 yearsAndroid Studio reports that Variable 'runnableCode' might not have been initialized.
-
JCarlosR over 3 yearsWould be helpful to add an example of a Handler running on a separate thread, for tasks that do not need to update ui.
-
Awesome-o almost 3 yearsCan you clarify how TimerTask is
Unreliable (doesn't always work)
? I clicked on all the links and I couldn't find one that actually clarified this. The first link also appears to be dead. Additionally, how up-to-date is this information? What if you only support Android 7+? -
Suragch almost 3 years@Awesome-o, Good question. It's been so long since I've written this that I don't remember myself. If you read all of those links and there is nothing to support "Unreliable (doesn't always work)" then maybe this should be removed from the list. Feel free to edit it out of my answer (along with the dead link). As far as how up-to-date this answer is, I would still assume that an Android class would be better than a plain Java one, but I'm focusing on Flutter now so I've fallen behind in my current Android knowledge.