Задача Android ASync ProgressDialog не отображается, пока фоновый поток не завершится

У меня есть активность Android, которая захватывает RSS-канал из URL-адреса и использует синтаксический анализатор SAX для привязки каждого элемента из XML в массив. Все это прекрасно работает, но, как и ожидалось, занимает немного времени, поэтому я хочу использовать AsyncActivity, чтобы сделать это в фоновом режиме. Мой код выглядит следующим образом:

class AddTask extends AsyncTask<Void, Item, Void> {

    protected void onPreExecute() {
        pDialog = ProgressDialog.show(MyActivity.this,"Please wait...", "Retrieving data ...", true);
    }

    protected Void doInBackground(Void... unused) {
        items = parser.getItems();

        for (Item it : items) {
            publishProgress(it);
        }
        return(null);
    }

    protected void onProgressUpdate(Item... item) {
        adapter.add(item[0]);
    }

    protected void onPostExecute(Void unused) {
        pDialog.dismiss();
    }
  }

Я вызываю onCreate() с

new AddTask().execute();

Строка items = parser.getItems() отлично работает - items является arraylist, содержащий каждый элемент из XML. Проблема, с которой я столкнулся, заключается в том, что при запуске операции ProgressDialog, который я создаю в onPreExecute(), показывается только после завершения метода doInBackground(). т.е. я получаю черный экран, длинную паузу, а затем полностью заполненный список с элементами. Почему это происходит? Почему рисунок пользовательского интерфейса не отображается, отображается ProgressDialog, парсер получает элементы и постепенно добавляет их в список, а затем отклоняется ProgressDialog?

Ответы

Ответ 1

Это работает для меня

@Override
protected void onPreExecute() {
        dialog = new ProgressDialog(viewContacts.this);
        dialog.setMessage(getString(R.string.please_wait_while_loading));
        dialog.setIndeterminate(true);
        dialog.setCancelable(false);
        dialog.show();
    }

Ответ 2

Я подозреваю, что что-то блокирует ваш поток пользовательского интерфейса после выполнения задачи. Например, я видел, как люди делали такие вещи:

MyTask myTask = new MyTask();
TaskParams params = new TaskParams();
myTask.execute(params);
myTask.get(5000, TimeUnit.MILLISECONDS);

Здесь вызывается блокировка потока пользовательского интерфейса (который, вероятно, откручивает задачу здесь...), что предотвратит любые связанные с UI элементы в вашей задаче onPreExecute() до тех пор, пока задача не завершится. Упс! Надеюсь это поможет.

Ответ 3

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

Правильный способ сделать это - передать экземпляр Activity в конструктор AsyncTask конструктором и завершить все, что вы хотите сделать в AsyncTask.onPostExecution().

Ответ 4

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

Результат передается как параметр в этом методе, если указан как третий тип общего типа.

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