Android java.util.Timer с возможностью сброса - PullRequest
2 голосов
/ 06 декабря 2011

У меня есть сценарий, в котором мне нужно выполнить определенную задачу с определенным интервалом, однако я хочу иметь возможность сбросить / перезапустить таймер без повторного создания. Вот мой код для лучшего понимания.

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;
    }

Идея, лежащая в основе этой реализации, заключается в том, что beatDetected() может вызываться из внешнего события, и в этом случае следующий тик таймера должен произойти с того момента, то есть истекшее время для следующей задачи должно быть сброшено. Однако я получаю только первый тик, и с этого момента таймер просто не работает. Я не ограничен использованием класса Timer, все, что решит описанный выше сценарий, будет работать. Я думал об использовании postDelayed, но этот код находится в Сервисе, и мне не нужны обновления, поддерживающие поток пользовательского интерфейса.

Ответы [ 2 ]

10 голосов
/ 06 декабря 2011

Использование отдельного потока для таймера считается несколько плохой практикой на устройствах Android. Это потому, что вы собираетесь тратить ресурсы в большинстве сценариев.

Если вам не нужны сверхточные временные события, вам следует использовать таймеры на основе Handler. Пример такого таймера можно увидеть здесь: Повторить задачу с задержкой? . Этот подход работает как для деятельности, так и для услуг.

Также имейте в виду, что таймеры на основе Handler и Timer будут приостановлены, если устройство перейдет в спящий режим. Если это не то, что вам нужно, используйте AlarmManager (но имейте в виду, что неправильное использование AlarmManager может привести к очень плохой работе батареи).


Сброс таймера Handler:

 void resetRepeatingTask() {
     mHandler.removeCallbacks(mBeatDetector);
     mHandler.postDelayed(mBeatDetector, mInterval);         
 }
3 голосов
/ 21 июня 2016

Принятый ответ не работает (по крайней мере, не для меня).

Простое решение использует Timer для запуска TimerTask, который можно легко сбросить.

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);

Обратите внимание, что новый TimerTask должен создаваться каждый раз при сбросе таймера - вы не можете повторно использовать старый. Если вы хотите сохранить состояние, вам нужно получить задачу таймера для запуска отдельной задачи.

...