0

這個問題與需要殺死ProgressDialogAsyncTask有關。在任務正在運行時,活動會被破壞並重新創建(例如,電話輪換)。一個新的對話框在onSaveInstanceState()的幫助下完成,但AsyncTask,由以前銷燬的活動產生,看不到它。ProgressDialog,activity的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

在這裏添加你正在執行asynctask的行。 – Sajmon 2013-03-13 22:13:03

+0

已添加,但我不確定是否有幫助。很通用。 – JamieB 2013-03-13 22:22:57

+0

當舊的活動被銷燬時,你能鉤住一些代碼來更新m_d嗎? – 2013-03-13 22:26:19

回答

1

存在兩個問題:第一個問題是AsyncTask被綁定到創建它的活動。我的意思是,活動的實例。

如果您希望它在活動輪換之間生存,則必須將其存儲在其他位置(例如,檢查this)。無論如何,你需要從新的活動中引用它(你可以做的另一件事是使用模型片段,即沒有UI的片段被設置爲setRetainInstance(true))。

一旦您從新創建的活動中引用了異步任務,沒有什麼能夠阻止您對異步任務具有局部本地m_d以及使用新對話更新它的setter方法。

還要注意,爲了允許垃圾回收,指向活動和對話框本身的弱引用是一個好習慣。否則,對話框(以及可能的活動本身)將不會被釋放,直到任務本身的執行結束。

+0

實際工作的甜耶穌。對於那些在家裏玩的人來說,祕密調查使用「onRetainNonConfigurationInstance」來返回首次創建的AsyncTask。當活動被銷燬並由Android重新編寫時,新實例使用getLastNonConfigurationInstance獲取指向原始AsyncTask的指針。然後它可以像m_switcharoo.setDialog(m_d)那樣調用它,然後在Switcharoo內部將它自己的m_d賦值爲傳入的值,這是新的對話框。 – JamieB 2013-03-13 23:29:43

+0

還要注意,片段顯然取代了所有這些,這些調用在API 13中被棄用,但是我正在針對API 8編碼。 – JamieB 2013-03-13 23:30:37