Запуск многих Asynctask по таймеру (таймер обратного отсчета)

Я создал CountDownTimer вот так

public class MyCountDownTimer extends CountDownTimer {
        public MyCountDownTimer(long startTime, long interval) {
        super(startTime, interval);
        }

        @Override
        public void onFinish() {
        //timeout
        }

        @Override
        public void onTick(long millisUntilFinished) { 
         PaymentAsyncTask paymentTask = new PaymentAsyncTask(this);
         paymentTask.execute();

        }
}

в onPostExecute из paymentTask я выполняю некоторые операции при определенных условиях.

По сути, я проверяю с какого-то веб-сайта, через какой-то промежуток времени (скажем, 3 секунды) задача была выполнена или нет.

Теперь, если Интернет работает быстро, с этим кодом проблем нет.

если задача завершается, я отменяю таймер в onPostExecute и делаю свою дальнейшую работу.

Но если интернет работает медленно, что означает, что ответ не приходит в течение 3 секунд, onPostExecute вызывается более одного раза (выполнение кода внутри него более одного раза), а задача был уже завершен, просто я получил ответ с опозданием из-за проблемы с сервером/задержки в Интернете.

Как я могу убедиться, что код внутри onPostExecute вызывается только один раз?

Возможные подходы:

  1. Возьмите какую-нибудь переменную статического флага, сделайте ее истинной и проверьте другие...

Я ищу надежное решение, возможно, Android предоставляет какой-то механизм для синхронизации этого. Спасибо.


person Sunny    schedule 18.04.2013    source источник


Ответы (2)


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

Пожалуйста, используйте свой объект AsyncTask глобально в своем классе Activity.

Фрагмент кода:

public class MyCountDownTimer extends CountDownTimer {
    PaymentAsyncTask paymentTask = null;

      public MyCountDownTimer(long startTime, long interval) {
            super(startTime, interval);
      }

      @Override
      public void onFinish() {
        //timeout 
      }

      @Override
      public void onTick(long millisUntilFinished) { 
        if(paymentTask == null) {
            android.util.Log.i("TAG", "Null");
            paymentTask = new PaymentAsyncTask(this);
            paymentTask.execute();
        } else {
            //Depending on your situation take appropriate action
            android.util.Log.i("TAG", "Not Null");
            if(paymentTask.getStatus() == (AsyncTask.Status.PENDING)) {
                //Indicates that the task has not been executed yet.
                android.util.Log.i("TAG", "Pending");
            } else if(paymentTask.getStatus() == (AsyncTask.Status.RUNNING)) {
                //Indicates that the task is running.
                android.util.Log.i("TAG", "Running");
            } else if(paymentTask.getStatus() == (AsyncTask.Status.FINISHED)) {
                //Indicates that AsyncTask.onPostExecute has finished.
                android.util.Log.i("TAG", "Finished");
            } 
        }
      }
}

Надеюсь, это поможет вам.

Спасибо.

person Community    schedule 18.04.2013
comment
Спасибо за подробное объяснение. Мой вопрос именно в этом, если при следующем вызове onTick() моя предыдущая задача ожидает/выполняется из-за сетевой задержки, в этом случае я не могу ее выполнить, потому что она уже находится в ожидании/выполняется. Предположим, я начинаю свою задачу с «x = 3» секунды, onTick будет снова вызываться с «x = 6», а моя задача, начатая с x = 3, все еще находится в ожидании с x = 6.. но мне нужно получить новый статус в x=6, поэтому мне нужно запускать задачи при каждом x=3n. просто, когда один из них возвращает мне ответ «хорошо», я хочу, чтобы все другие задачи запускались после того, как пришло время, чтобы сказать ... ПРЕРЫВАНИЕ !!! - person Sunny; 18.04.2013
comment
Я хочу запускать каждую задачу с x=3n, но когда одна из них запускается с x=t, возвращается "ok", я не хочу выполнять код, написанный внутри onPostExecute всех других задач, запущенных после x=t, немного длинно, но надеюсь ты понял мою мысль.. - person Sunny; 18.04.2013
comment
@Sunny В зависимости от статуса вы можете отменить текущую задачу и начать новую задачу или продолжить выполнение текущей задачи. - person ; 19.04.2013
comment
согласно моему требованию, я должен запускать новую задачу для каждого onTick, иначе как я получу новый статус? поэтому отмена задачи может быть не очень хорошей идеей, теперь я беру одно глобальное логическое значение, которое я устанавливаю в значение true всякий раз, когда получаю ответ «хорошо», и все проверки postExecute для этого глобального перед дальнейшим выполнением. - person Sunny; 19.04.2013

пожалуйста, проверьте, что это полезно для вас, как http://daniel-codes.blogspot.in/.. .

Выполняется ли ваша AsyncTask?

Короткое примечание об AsyncTask: до версии 4.0 (и, возможно, до версии 3.0, но я не проверял) AsyncTask.getStatus() может вам лгать. Если AsyncTask отменен, он не установит статус правильно; вместо этого он останется ВЫПОЛНЕННЫМ после завершения AsyncTask.onCancelled().

Моей первоначальной мыслью было использовать AsyncTask.isCancelled(), но вы можете столкнуться с некоторыми проблемами параллелизма, если пытаетесь оценить, выполняется ли AsyncTask из другого потока. Отмененная задача AsyncTask не обязательно завершается в тот момент, когда вы ее отменяете; на самом деле, если вы не проверяете isCancelled() регулярно в doInBackground(), вы можете в конечном итоге запустить AsyncTask на некоторое время после отмены.

Мое решение состоит в том, чтобы установить логическое значение в конце onCancelled(), которое укажет системе, что вы дошли до конца выполнения. Вот пример написания AsyncTask, где вы можете точно знать, когда он был завершен:

private class MyAsyncTask extends AsyncTask {
  private boolean mFinishedCancel = false;

  protected Void doInBackground(Void... params) {
    return null; // You'd normally do something here
  }

  protected void onCancelled() {
    mFinishedCancel = true;
  }

  public boolean isFinished() {
    return getStatus() == Status.FINISHED || mFinishedCancel;
  }
}
person SBJ    schedule 18.04.2013
comment
это означает, что брать флаг, когда это необходимо, - неплохая идея.. позвольте мне проверить этот подход... Как я упоминал в первом подходе, использование флага помогло бы, но я просто подумал, могу ли я просто избежать игры с флагами, потому что это связано с оплатой ... я не хочу никаких ошибок в этом сложном сценарии в реальном времени ... тщательное тестирование поможет делу, я думаю ... :) - person Sunny; 18.04.2013