Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android java.util.Timer with reset option

I have a scenario where I need to run a certain task at specific interval, however, I want to be able to reset/restart the timer without reinstantiating. Here's my code for better understanding.

private TimerTask beatTask = new TimerTask() {
        @Override
        public void run() {
            beatDetected();
        }
    };

public void beatDetected() {
        timeoutTimer.cancel();

        // handle my stuff and restart the timer.

        timeoutTimer.schedule(beatTask, 2000);
    }

@Override
public int onStartCommand(Intent intent, int flags, int startId) {

        (timeoutTimer = new Timer()).schedule(beatTask, 2000);

        return Service.START_STICKY;
    }

The idea behind this implementation is that beatDetected() can be called from outside event, in which case the next timer tick should happen from that moment on i.e. the elapsed time for the next task should be reset. However, I only get the first tick, and from that point on, the timer just doesn't work. I'm not limited to using Timer class, anything that will solve the above scenario will work. I was thinging about using postDelayed, but this code is located in a Service, and I don't really need UI thread aware updates.

like image 713
Tomislav Markovski Avatar asked Dec 03 '22 06:12

Tomislav Markovski


2 Answers

Using separate thread for timer is considered a somewhat bad practice on Android devices. That's because you are going to waste resources in most scenarios.

If you don't need super precise timing events, you should go with Handler based timers. An example of such timer can be seen here: Repeat a task with a time delay?. This approach works both for Activities and Services.

Also keep in mind that both Handler and Timer based timers will be paused if device goes to sleep mode. If this is not what you need, then use AlarmManager (but keep in mind that using AlarmManager incorrectly may lead to very bad battery performance).


Reseting the Handler based timer:

 void resetRepeatingTask() {
     mHandler.removeCallbacks(mBeatDetector);
     mHandler.postDelayed(mBeatDetector, mInterval);         
 }
like image 182
inazaruk Avatar answered Dec 05 '22 19:12

inazaruk


The accepted answer does not work (at least not for me).

A simple solution uses a Timer to trigger a TimerTask, which can easily be reset.

Log.d(TAG, "Restarting timer");
if (timer != null) {
    timer.cancel();
}
timer = new Timer();
timer.schedule(new TimerTask() {
    @Override
    public void run() {
        Log.d(TAG, "Run the task");
    }
}, 1000);

Note that a new TimerTask must be created every time you reset the timer - you can't reuse the old one. If you want to preserve state you will need to get the timer task to run a separate task.

like image 26
IanS Avatar answered Dec 05 '22 19:12

IanS