0

Этот вопрос связан с AsyncTask, которому необходимо убить ProgressDialog. Пока задача запущена, активность уничтожается и воссоздается (например, поворот телефона). Новое диалоговое окно создается с помощью onSaveInstanceState(), но AsyncTask, порожденный ранее разрушенным действием, не может его увидеть.ProgressDialog, деятельность onCreate() и AsyncTask

Картинка, если вы ... (быстрый код макета, например, ради).

public class Bob extends Activity { 

    private ProgressDialog m_d; 

    public void onCreate(Bundle b) { 
     m_d = new ProgressDialog(this); 
     // ... 
     if (b != null) { 
      if (b.getBoolean("dialog") == true) 
       m_d.show(); 
     } 
     // ... 
    } 

    public void onSaveInstanceState(Bundle b) { 
     super.onSaveInstanceState(b); 
     b.putBoolean("dialog", (m_d.isShowing())); 
    } 

    public void onDestroy() { 
     if (m_d.isShowing()) { 
      m_d.dismiss(); 
      m_d = null; 
     } 
     //... 
    } 
} 

AsyncTaskonPreExecute() делает m_d.show() и onPostExecute() делает m_d.hide().

Проблема заключается в том, что моя деятельность воссоздается (скажем, по телефону), AsyncTask, похоже, имеет старый m_d. Это null, потому что это было убито в onDestroy().

У этого нет новых m_d, созданных при восстановлении активности. Итак, теперь у меня есть ProgressDialog, и парень, который должен был убить его в onPostExecute(), не может его увидеть.

Теперь что? Мне нужен старый AsyncTask, чтобы как-то сигнализировать о новом ProgressDialog, чтобы уйти.

private OnItemSelectedListener onSpinnerSelection = new OnItemSelectedListener() { 

    public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3) { 
     // ... 
     new Switcharoo().execute(); 
    } 
} 

private class Switcharoo extends AsyncTask<Void, Void, Void> { 

    protected void onPreExecute() { 
     m_d.show(); 
     // ... 
    } 

    protected void onPostExecute() { 
     if (m_d != null) m_d.hide(); 
     // ... 
    } 

    protected Void doInBackground(Void... arg0) { 
     // ... 
    } 
} 

Если Android не убивает мою активность во время выполнения задачи, все в порядке. ProgressDialog всплывает и уходит, как я ожидаю.

Если Android решает перезагрузить деятельность по какой-либо причине во время выполнения задания, m_d будет onPostExecute()null хотя я воссоздал его в onCreate() - у него есть старый m_d, а не новый.

+0

добавьте сюда строку, в которой выполняется асинхронная операция. – Sajmon

+0

Добавлено, хотя я не уверен, что это помогает. Довольно общий. – JamieB

+0

Можете ли вы перехватить код для обновления m_d при уничтожении старой активности? –

ответ

1

Есть две проблемы: во-первых, AsyncTask привязан к деятельности, которая ее создала. Я имею в виду пример действия.

Если вы хотите, чтобы он выжил между поворотами деятельности, вы должны его хранить в другом месте (например, отметьте this). В любом случае вам нужно иметь ссылку на него из нового действия (другое, что вы могли бы сделать, это использовать фрагмент модели, то есть фрагмент без интерфейса пользователя, который вы установили как setRetainInstance(true)).

Как только у вас есть ссылка на задачу async из вновь созданной активности, ничто не мешает вам иметь m_d локальную задачу async и метод setter, который обновляет его с помощью нового диалогового окна.

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

+0

Сладкий Иисус, который действительно работал.Для тех, кто играет дома, секретный соус использует «onRetainNonConfigurationInstance», чтобы вернуть AsyncTask, который был впервые создан. Когда действие уничтожается и переделывается Android, новый экземпляр использует getLastNonConfigurationInstance, чтобы получить указатель на исходную AsyncTask. Затем он может вызвать soemthing, например m_switcharoo.setDialog (m_d), а затем внутри Switcharoo присваивает свой собственный m_d значение переданного значения, которое является новым диалоговым окном. – JamieB

+0

Обратите также внимание, что фрагменты, очевидно, заменили все это, и эти вызовы устарели в API 13, но я кодирую API 8. – JamieB

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