Задача 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
, чтобы присвоить результат работы фона члену вашего вызывающего класса.
Результат передается как параметр в этом методе, если указан как третий тип общего типа.
Таким образом, ваш поток пользовательского интерфейса не будет заблокирован, как указано выше. Вы должны позаботиться о любом последующем использовании результата вне подкласса, хотя, поскольку фоновый поток все еще может работать, и ваш член не будет иметь нового значения.