Как я могу показать ProgressBar только после минимальной задержки?

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

Есть ли способ отложить отображение индикатора выполнения без создания еще одного вложенного AsyncTask?


person Jeff Axelrod    schedule 21.07.2012    source источник


Ответы (3)


Да, он существует, и он называется CountDownTimer, и он крайне недооценен. Вы можете предпринимать действия на каждом такте таймера или когда таймер истечет.

person Code Droid    schedule 21.07.2012

Благодаря Code Droid я смог написать абстрактный класс AsyncTask, который показывает неопределенный индикатор выполнения после указанной задержки. Просто расширьте этот класс вместо AsyncTask и обязательно вызовите super(), когда это уместно:

public abstract class AsyncTaskWithDelayedIndeterminateProgress
      <Params, Progress, Result> extends AsyncTask<Params, Progress, Result> {
   private static final int MIN_DELAY = 250;
   private final ProgressDialog progressDialog;
   private final CountDownTimer countDownTimer;

   protected AsyncTaskWithDelayedIndeterminateProgress(Activity activity) {
      progressDialog = createProgressDialog(activity);
      countDownTimer = createCountDownTimer();
   }

   @Override protected void onPreExecute() {
      countDownTimer.start();
   }

   @Override protected void onPostExecute(Result children) {
      countDownTimer.cancel();
      if(progressDialog.isShowing())
         progressDialog.dismiss();
   }

   private ProgressDialog createProgressDialog(Activity activity) {
      final ProgressDialog progressDialog = new ProgressDialog(activity);
      progressDialog.setIndeterminate(true);
      return progressDialog;
   }

   private CountDownTimer createCountDownTimer() {
      return new CountDownTimer(MIN_DELAY, MIN_DELAY + 1) {
         @Override public void onTick(long millisUntilFinished) { }

         @Override public void onFinish() {
            progressDialog.show();
         }
      };
   }
person Jeff Axelrod    schedule 27.07.2012

Я предполагаю, что вы вызываете onProgressUpdate по крайней мере несколько раз, прежде чем ваша AsyncTask будет завершена. Если это так, то вы могли бы сделать это. Каждый раз перед вызовом onProgressUpdate вызывайте Thread.sleep(250). Таким образом, ваш фоновый поток будет приостановлен перед общением с потоком пользовательского интерфейса и создаст видимость более длительной задачи. В противном случае мне, вероятно, понадобится увидеть ваш код или получить дополнительную информацию.

person Swifty McSwifterton    schedule 21.07.2012
comment
Извините, это неопределенный ProgressBar. Я не хочу создавать задержку только для того, чтобы она выглядела более приятной, я хочу вообще избежать отображения, если только задержка не начнет превышать, скажем, 250 мс. - person Jeff Axelrod; 21.07.2012
comment
Ладно, попался. Теперь это имеет для меня больше смысла. Какая у вас фоновая операция? - person Swifty McSwifterton; 21.07.2012
comment
В этом случае я решил это другим способом, но в будущем я хочу применить это к таким вещам, как загрузки или операции с интенсивным использованием ЦП. Некоторые устройства или сетевые подключения могут реагировать достаточно быстро, чтобы не вызвать всплывающее окно «Подождите», а другие, более медленные, могут. Хотя я не уверен, что мы просто не сдвинули задачу на 250 мс вперед, задержав отображение индикатора выполнения. Если бы операция заняла 251 мс, вы, конечно, все равно получили бы мерцание/глюк, но добавление задержки в 100 мс могло бы сделать ее более плавной и не иметь такого большого относительного влияния на производительность. - person Jeff Axelrod; 21.07.2012