Как проверить, закончили ли все AsyncTasks?

у меня 3 AsyncTasks и 1 ProgressBar. Я хочу, когда любая из задач выполняется, индикатор выполнения виден, и когда все они заканчиваются, индикатор выполнения невидим.

в Java есть ExecutorService::isTerminated чтобы проверить, все ли runnables закончены, но Android нет.

Update: 3 задачи выполняются одновременно.

рис. enter image description here

9 ответов


хорошая графика. Но я боюсь, что для этого нет встроенного механизма. Вам придется реализовать его самостоятельно. Есть несколько решений, которые вы могли бы использовать -

  1. сохранить ссылку на все 3 задачи. Когда задача завершится, проверьте, завершены ли две другие задачи, если да, то закройте диалоговое окно выполнения, если нет, дождитесь завершения другой задачи и проверьте еще раз. Убедитесь, что вы освободите ссылки, когда закончите.
  2. Если вы не хотите держать эталонный магазин a счетчик. Когда задача завершится, увеличьте счетчик и проверьте, равен ли он 3. Если все задачи выполнены и вы закончили. Если вы реализуете это, убедитесь, что синхронизирован доступ к счетчику.

попробуйте использовать AsyncTask.getStatus (). Это прекрасно работает. См. ниже пример кода.

 List<AsyncTask<String, String, String>> asyncTasks = new ArrayList<AsyncTask<String, String, String>>();
 AsyncTask<String, String, String> asyncTask1 = new uploadTask().execute(string);
 AsyncTask<String, String, String> asyncTask2 = new downloadTask().execute(string);
 AsyncTask<String, String, String> asyncTask3 = new createTask().execute(string);
 asyncTasks.add(asyncTask1);
 asyncTasks.add(asyncTask2);
 asyncTasks.add(asyncTask3);

вы можете позже зациклить AsyncTaskList и найти состояние каждой из задач, как показано ниже.

 for(int i=0;i<asyncTasks.size();i++){
      AsyncTask<String, String, String> asyncTaskItem = (AsyncTask<String, String, String>)asyncTasks.get(i);
      // getStatus() would return PENDING,RUNNING,FINISHED statuses
      String status = asyncTaskItem.getStatus().toString();
      //if status is FINISHED for all the 3 async tasks, hide the progressbar
 }

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

лучшим подходом было бы создать отдельный класс, который расширяет AsynTask и определяет интерфейс обратного вызова, который запускается в onPostExecute.


создать поле для хранения всех задач:

private ArrayList<HtmlDownloaderTask> mTasks;

запустить свои задачи таким образом:

HtmlDownloaderTask = new HtmlDownloaderTask(page.getHtml());
task.execute(page.getUrl());
//if you want parallel execution try this:
//task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR,page.getUrl());
mTasks.add(task);

на onPostExecute MyAsyncTask:

int unfinishedTasks = 0;
for (HtmlDownloaderTask myDT : mTasks){
    if(!(myDT.getStatus() == AsyncTask.Status.FINISHED)){
        unfinishedTasks++;
    }
}
if (unfinishedTasks == 1){
    //We are all done. 1 Because its the current one that hasnt finished post execute
    callWhateverMethod();

}

Ну как вы знаете, когда AsyncTask заканчивается (когда onPostExecute вызывается): одним из решений может быть создание метода setProgressBarVisible() который сохраняет счетчик и при первом вызове устанавливает видимый, и метод setProgressBarInvisible() это уменьшает счетчик и когда ноль устанавливает индикатор выполнения невидимым.


:-? я думаю, это просто трюк. вы вернете сообщение в onPostExecute каждого Asyntask и сравнить его. (это сообщение может содержать время, например)


официальная поддержка CompletableFuture был введен с уровня API 24.

Он также доступен в Java 8 здесь.

можно использовать просто использовать что-то вроде:

taskA.thenCombine(taskB).thenCombine(taskC)

Я бы просто уведомил его в onPostExecute() см. onPostExecute и 4 шага в документе для деталей и вы можете использовать EventBus делать некоторые вещи.


попробуйте это, возможно, может помочь вам...

            final ImageUploader _upload = new ImageUploader();
            _upload.setValue(getApplicationContext(), _imagepath, _urlPHP);
            _upload.execute();
            Runnable _run;
            Handler _h2;
            _run = new Runnable() {
                public void run() {
                    _h2 = new Handler();
                    _h2.postDelayed(this, 1000);
                    Toast.makeText(getApplicationContext(), "not finished", Toast.LENGTH_LONG).show();

                    if (_upload.getStatus() == AsyncTask.Status.FINISHED) {
                        Toast.makeText(getApplicationContext(), "finished", Toast.LENGTH_LONG).show();
                        _h2.removeCallbacks(_run);

                    }
                }
            };
            _h2 = new Handler();
            _h2.postDelayed(_run, 1);