Как изменить скорость или период повторяющейся задачи с помощью ScheduledExecutorService?

У меня есть модифицированная версия примера приложения Bluetooth-чата. Я настроил ScheduledExecutorService, который отправляет команду по bluetooth с заданной скоростью, используя scheduleAtFixedRate.

Я установил PreferenceActivity, чтобы пользователь мог изменять период. Но я не уверен, как заставить повторяющиеся задачи выполняться с обновленным периодом. Нужно ли как-то отменить и перезапустить ScheduledExecutorService?

Вот соответствующие части моего кода.

private ScheduledExecutorService scheduleTaskExecutor;

public long ReadInterval = 1;

...    

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
        scheduleTaskExecutor = Executors.newScheduledThreadPool(5);
...
    // This schedule a task to run every 1 second:
    scheduleTaskExecutor.scheduleAtFixedRate(new Runnable() {
      public void run() {


        // If you need update UI, simply do this:
         runOnUiThread(new Runnable() {
            public void run() {
            // update your UI component here.
              if (connected == true) {
                  sendMessage("READ");                
                  if (D) Log.i(TAG, "In Run!");                   
              }
            }
        });
      }
    }, 0, ReadInterval, TimeUnit.SECONDS);      
    }

И я пытался обновить ReadInterval здесь. ReadInterval обновляется, но период повторяющейся команды не обновляется.

    @Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (D)
        Log.d(TAG, "onActivityResult " + resultCode);
    switch (requestCode) {
    case REQUEST_CONNECT_DEVICE:
...
    case REQUEST_ENABLE_BT:
...
    case REQUEST_SETTINGS:
        // When returning from settings activity
        SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
        String Pref = sharedPref.getString(SettingsActivity.KEY_PREF_READINTERVAL, "");
        ReadInterval = Long.valueOf(Pref);
        Toast.makeText(this, Pref,
                    Toast.LENGTH_SHORT).show();

        Log.d(TAG, "Settings Activity Result");
    }
}

person greencardigan    schedule 20.02.2015    source источник
comment
посмотрите на следующий постhttp://stackoverflow.com/questions/1519091/scheduledexecutorservice-with-variable-delay   -  person sasankad    schedule 20.02.2015


Ответы (1)


Я немного улучшил ответ (в основном потому, что мне тоже пришлось использовать ScheduledExecutorService). Пожалуйста, используйте этот код вместо предыдущего, который я разместил, потому что предыдущий был действительно производительным без веской причины.

private ScheduledExecutorService scheduledExecutorService;
private ScheduledFuture<?> futureTask;
private Runnable myTask;

@Override
public void onCreate(Bundle savedInstanceState) 
{
    super.onCreate(savedInstanceState);

    // Your executor, you should instanciate it once for all
    scheduledExecutorService = Executors.newScheduledThreadPool(5);

    // Since your task won't change during runtime, you can instanciate it too once for all
    myTask = new Runnable()
    {
        @Override
        public void run()
        {
            // Your code to run periodically
        }
    };
}

/**
 * This method will reschedule "myTask" with the new param time
 */
public void changeReadInterval(long time)
{
    if(time > 0)
    {       
        if (futureTask != null)
        {
            futureTask.cancel(true);
        }

        futureTask = scheduledExecutorService.scheduleAtFixedRate(myTask, 0, time, TimeUnit.SECONDS);
    }
}

Теперь, чтобы перепланировать задачу во время выполнения, используйте метод changeReadInterval(time);

Он отменит предыдущий «таймер», если он был установлен, и переназначит новый.

person Nino Lenoska    schedule 20.02.2015
comment
Спасибо, это сработало. - person greencardigan; 25.02.2015
comment
@greencardigan Я обновил ответ улучшенным кодом. Предыдущий был довольно плохим и не таким элегантным! - person Nino Lenoska; 25.02.2015
comment
Это выглядит лучше. Однако мне пришлось изменить scheduleTaskExecutor = Executors.newScheduledThreadPool(5) на ScheduleExecutorService = Executors.newScheduledThreadPool(5), чтобы заставить его работать. - person greencardigan; 26.02.2015
comment
Не забудьте scheduledExecutorService.setRemoveOnCancelPolicy(true), чтобы предотвратить утечку памяти (см., например, stackoverflow.com/a/23370049/1052284< /а>) - person Mark Jeronimus; 13.09.2018