ProgressDialog не отображается, когда AsyncTask.get () называется

Возможный дубликат:
AsyncTask блокирует пользовательский интерфейс и показывает индикатор прогресса с задержкой

Я хочу показать progressDialog при извлечении JSON с любого сервера. Поэтому я использовал AsyncTask в качестве решения (не уверен в другом выходе).

Все в порядке, ProgressDialog работает правильно, пока я не вызову метод .get (), используя экземпляр AsyncTask. Полагаю, что это блокирует пользовательский интерфейс. Вот мой AsyncTask:

public class myAsync extends AsyncTask<String, String, List> { String message; // for dialog message ProgressDialog progress; Intent myIntent; Context ctx; public myAsync(String message, Context ctx) { this.message = message; this.ctx = ctx; progress = new ProgressDialog(ctx); } @Override protected void onPreExecute() { progress.setMessage(message); progress.setIndeterminate(true); progress.setCancelable(false); progress.show(); } @Override protected List doInBackground(String... params) { //returns any list after the task return anyList; } @Override protected void onPostExecute(List result) { if(progress.isShowing()) progress.dismiss(); } } 

И вот myActivity, который вызывает AsyncTask:

 myAsync asyncTask = new myAsync("Loading...", this); asyncTask.execute("Any string", "Other string"); asyncTask.get(); // If I comment out this line, ProgressDialog works 

После выполнения, когда я попытался записать результат из doInBackground и onPostExecute, проблема не возникает. Но если я хочу получить с .get () результат, ProgressDialog не отображается или показывается так мало времени (может быть, 0,2 секунды)

В чем проблема?

Да, get() ждет, если это необходимо для завершения вычисления, а затем извлекает его результат. Это означает, что вы блокируете поток пользовательского интерфейса, ожидая результата.

Решение: не вызывайте get

Обычно вы вызываете функцию (обратный вызов) в postExecute .

Вызов .get() изменяет вашу AsyncTask в эффективную « SyncTask », поскольку она вызывает текущий поток (который будет потоком пользовательского интерфейса), чтобы дождаться завершения AsyncTask его обработки. Поскольку теперь вы блокируете поток пользовательского интерфейса, вызов метода .show() для ProgressDialog никогда не даст возможность диалогу сделать сам экран.

Удаление вызова позволит ему правильно работать в фоновом режиме.

Если вам нужно выполнить обработку после завершения задачи, я предлагаю вам либо поместить ее внутри метода onPostExecute , либо использовать обратный вызов для Activity из onPostExecute .

Если я правильно понял ваш вопрос, вам необходимо обновить ход вашей AsyncTask в ProgressDialog и это не работает в настоящее время. Итак, несколько замечаний: я не уверен, чего вы пытаетесь достичь с помощью .get() но я предполагаю, что вы хотите отобразить прогресс.

Я изменил вашу программу ниже, чтобы обновить поток пользовательского интерфейса с прогрессом AsyncTask. Каждый раз, когда вам нужно обновить прогресс, обновите эту переменную prog в методе doInBackground .

 public class myAsync extends AsyncTask<String, Integer, List> { String message; // for dialog message ProgressDialog progress; Intent myIntent; Context ctx; public myAsync(String message, Context ctx) { this.message = message; this.ctx = ctx; progress = new ProgressDialog(ctx); } @Override protected void onPreExecute() { // Runs on the UI thread progress.setMessage(message); progress.setIndeterminate(true); progress.setCancelable(false); progress.show(); } @Override protected List doInBackground(String... params) { // Runs in the background thread // publish your progress here!! int prog = 5; // This number will represent your "progress" publishProgress(prog); return anyList; } protected void onProgressUpdate(Integer... progress) { // Runs in the UI thread // This method will fire (on the UI thread) EVERYTIME publishProgress // is called. Log.d(TAG, "Progress is: " +progress); } @Override protected void onPostExecute(List result) { // Runs in the UI thread for (int i=0; i<result.size(); i++) { Log.d(TAG, "List item: " + result.get(i)); } if(progress.isShowing()) progress.dismiss(); } } 

Попробуйте использовать runOnUiThread следующим образом:

  runOnUiThread(new Runnable(){ public void run() { dialog.show(); }}); 

Запуск чего-то на AsyncTask означает, что он убегает от UIthread, поэтому обычно вы не можете запускать операции ui изнутри методов Async без обработчиков и т. Д., От которых я обычно держусь. Я также обрабатываю такое решение, создавая progressDialog как переменную в моем классе выше моего oncreate, чтобы он был видимым для всего класса. Затем я вызываю progressdialog прямо перед моей асинтемой, а затем, поскольку ее видимый для всего класса я вызываю .dissmiss () в onPostExecute