onPostExecute () вызывается, но он не закрывает мой диалог - PullRequest
1 голос
/ 15 ноября 2010

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

Проблема : странное поведение в том, что диалоговое окно прогресса отображается, но никогда не закрывается.

  • Я уверен, что onPostExecute () вызывается для каждого экземпляра задачи, так как любые операторы Log.d ("", "") запускаются, если помещены здесь, даже сообщения Toast отображаются внутри этого метода, но я не могу отклонить статический диалог.

  • Я понимаю, что AsyncTask (s) имеют доступ к потоку пользовательского интерфейса только в 2 местах [onPreExecute () и onPostExecute ()], поэтому я считаю, что пытаться закрыть диалог в runOnUiThread () не нужно.

  • Все вызовы executeTask () выполняются из разных методов onCreate () различных действий, которым необходимо извлечь некоторые данные по сети перед заполнением некоторых их элементов пользовательского интерфейса, и я всегда передаю контекст текущего действия задачам. ,

  • Поскольку я не переключаю действия до тех пор, пока соответствующие задачи не будут выполнены, я считаю, что объекты контекста действия все еще действительны (я ошибаюсь, предположив это ???). Я никогда не находил ни одного из них ноль во время отладки.

  • Может ли это быть проблемой синхронизации? Я также заметил, что в большинстве случаев DDMS показывает, что все задачи завершены за до , когда отображается активность. Если я использую new Handler().postDelayed(runnable_which_calls_these_tasks,10); в onCreate () и добавляю код задержки в foo_X (), действия отображаются без каких-либо задержек, но диалоговое окно просто не закрывается ().

Я прочитал довольно много статей по этому вопросу, но до сих пор не могу точно определить, где я ошибаюсь. Я не хочу определять каждую задачу как private inner class Task1 extends AsyncTask<> во всех моих классах активности, и я не хотел бы (если это не единственное решение) загружать в объект приложения все ссылки на действия, как указано в этом обсуждении: AsyncTask действительно концептуально ошибочен или я просто что-то упустил? .

Я потратил на это целую неделю и совершенно ничего не понимаю :( Было бы здорово, если бы кто-нибудь смог мне помочь, и дал бы мне знать, что мне не хватает.
Ниже приведено определение класса: [для ясности я удалил некоторый не относящийся к конкретному приложению код]

public class NetworkTask extends AsyncTask<Void, Integer, Boolean> {  

private  Context UIcontext;  
private int operationType;  
private static ProgressDialog dialog;
private static int taskCount;


private NetworkTask(int operationType Context context){  
    this.UIcontext = context; 
    this.operationType = operationType;
    if (taskCount++ == 0)  
        dialog = ProgressDialog.show(context,"","Loading...");

}  

public static Boolean executeTask(int operationType, Context context) {
    return new NetworkTask(operationType, context).execute().get(); 
}

@Override  
protected void onPreExecute(){  
    super.onPreExecute();  
    if (taskCount == 1)  
        dialog.show();  
}  

@Override
protected Boolean doInBackground(Void... arg0) {  
switch(operationType){  
    case TYPE_1:  
        foo1();  
        break;  
    case TYPE_2:  
        foo2();  
        break;  
    case TYPE_3:  
        foo3();  
        break;  
    case TYPE_4:  
        foo4();  
        break;  
}  

@Override
protected void onPostExecute(Boolean result) {
    super.onPostExecute(result);
    taskCount--;
    if (dialog.isShowing() && taskCount == 0){
            dialog.dismiss();
    }else {
        Toast.makeText(UIcontext, "Task#"+ operationType+", m done, but there are "+taskCount+" more", 5).show();
    }
}

}

1 Ответ

2 голосов
/ 15 ноября 2010

Отредактировано:

Загадка разгадана - эта проблема доставляла мне немного хлопот.Было несколько проблем:

  1. Основная проблема, из-за которой диалог не отображался, была NetworkTask.get().Это блокирующий вызов, который ожидает завершения всей сетевой задачи.В течение этого времени он блокирует поток пользовательского интерфейса, поэтому ничего не рисуется (также другие элементы пользовательского интерфейса не отвечают).Удалить get():

    public static Boolean executeTask(int operationType, Context context){
        new NetworkTask(operationType, context).execute();
        return true; // return whatever
    } 
    
  2. show() на ProgressDialog вызывается дважды.Это показывает два диалога, один за другим.Удалить show() внутри onPreExecute().

  3. ProgressDialog является модальным - он предотвращает изменение пользовательского интерфейса, пока это не будет сделано.Toast.makeText() вызываются до dialog.dismiss(), но, поскольку диалог блокирует рисование на экране, они ставятся в очередь и отображаются после закрытия диалога.

  4. super.onPostExecute(result) и super.onPreExecute() являются избыточнымипоэтому можно удалить.

Я могу опубликовать весь рабочий код, если у вас возникли проблемы с ним.

...