Изменение системных часов Android останавливает таймеры. Как я могу перезапустить их? - PullRequest
8 голосов
/ 12 июля 2010

Мне нужно запустить периодическое задание в приложении Android.В настоящее время я использую таймер, подобный следующему:

final Handler guiHandler = new Handler();

// the task to run
final Runnable myRunnable = new Runnable() {

    @Override
    public void run() {
        doMyStuff();
    }
};

Timer timer = new Timer();
timer.schedule(new TimerTask() {

    @Override
    public void run() {
        guiHandler.post(myRunnable);
    }
}, 0, 30000); // run every 30 seconds

Это делает именно то, что мне нужно, но есть проблема: если я изменю время на эмуляторе или телефоне, таймер останавливается.Это то, что появляется в журнале, когда я меняю время:

D/SystemClock(  331): Setting time of day to sec=1278920137
W/SystemClock(  331): Unable to set rtc to 1278920137: Invalid argument

Ничего о прерывании таймера, но он явно не работает после того, как системные часы изменились.Мне нужно, чтобы задача продолжала выполняться все время, пока запущено приложение.

Как я могу перезапустить таймер, если его остановить таким образом?В Timer или TimerTask нет способа проверить, запущен ли он в данный момент, поэтому я не знаю, когда его перенести.Есть идеи?

1 Ответ

4 голосов
/ 17 августа 2010

Я думаю, что есть несколько способов сделать это. Я бы не использовал таймер в любом случае.

Вы можете использовать обработчик для запуска вашей задачи в вызове postDelayed. Тогда ваша задача должна была бы перерегистрировать себя в обработчике изнутри себя.

final int ONE_SECOND = 1000; // one second
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
   public void run() {
      ... // do some stuff
      if (expression) {
         handler.postDelayed(this, ONE_SECOND);
      }
   }
}, ONE_SECOND);

Это сохранит задачу, пока ваше приложение живо. Вы также можете настроить скорость задержки в postDelayed в Runnable. Этот способ почти предсказуем, если вы сделаете еще один Looper. Использование основного потока может или не может быть целесообразным в зависимости от того, что задача.

Существует также AlarmManager, доступ к которому можно получить через интерфейс Context, который предназначен для повторяющихся задач с более точными интервалами. Его немного сложнее в использовании, но вы получаете гибкость от использования RTC и постоянных повторяющихся задач.

AlarmManager manager = mContext.getSystemService(Context.ALARM_SERVICE);
manager.setRepeating(AlarmManager.RTC, 
    <start_time_millis>, 
    <period_millis>, 
    pendingIntent);

Например, ожидающее намерение может запустить широковещательное намерение, которое вы можете прослушать в другом месте. Вы можете создать это отложенное намерение в onCreate вашего пользовательского объекта Application и отменить намерение в onTerminate ().

...