2010-11-15 2 views
1

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

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

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

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

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

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

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

Я прочитал довольно много статей по этому вопросу, но до сих пор не могу точно выяснить, где я иду не так. Я не хочу определять каждую задачу как private inner class Task1 extends AsyncTask<> во всех моих классах активности, и я бы не хотел (если это не единственное решение) загружать мой объект приложения со всеми ссылками на действия, как указано в этом обсуждении: Is AsyncTask really conceptually flawed or am I just missing something?.

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

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(); 
    } 
} 

}

ответ

2

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

Тайна решена - это один дает мне немного тро uble. Были несколько проблем:

  1. Основная проблема, почему диалог не показывал был NetworkTask.get(). Это блокирующий вызов, ожидающий завершения всей NetworkTask. За это время он блокирует поток пользовательского интерфейса, поэтому ничего не нарисовано (также другие элементы пользовательского интерфейса не реагируют).Удалить 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() являются излишними, поэтому их можно удалить.

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

+0

@Peter Как я упоминал ранее, я хочу централизованно управлять всеми своими сетевыми задачами с помощью этого класса. кол-во задач - это только статический счетчик, связанный с классом [уменьшенный на каждый возврат задачи и увеличиваемый при каждом задании. Мое намерение состоит в том, что диалог прогресса отображается первой задачей и отклоняется последним. [просто перепроверено, taskCount статична в моем коде, извините за опечатку здесь] – ritwaj

+0

@Peter Изменен код на основе вашего наблюдения, убедившись, что диалог показан и отклонен ровно один раз. Диалог не отображается вообще. – ritwaj

+0

Возможно, вы покажете это и немедленно отпустите. – Falmarri

Смежные вопросы