2012-12-22 103 views
0

我有一堆其中獲取數據AsyncTasks的。他們通過顯示對話框來更新進度。有時這會導致應用程序在後臺(不可見)時崩潰。我的代碼在下面調用。我可以做什麼檢查以防止應用程序崩潰,而無需完全重新設置對話框?從背景使用對話框崩潰的應用程序

這些在DownloadAsyncTask的聲明,並通過在構造

protected ProgressDialog mDialog; 
protected String mDialogMessage = "Loading Data"; 
protected ProgressBar progBar; 

doInBackground() { 
    if (mProgressBar != null && mProgressBar.getVisibility() == View.INVISIBLE) { 
     mUIThreadHandler.post(new Runnable() { 
      @Override 
      public void run() { 
       mProgressBar.setVisibility(View.VISIBLE); 
      } 
     }); 
    } else if (mDialog != null && !mDialog.isShowing()) { 
     mUIThreadHandler.post(new Runnable() { 
      @Override 
      public void run() { 
       mDialog.setMessage(mDialogMessage); 
       mDialog.show(); 
      } 
     }); 
    } 
} 

然後onPostExecute()

@Override 
protected void onPostExecute(DefaultHandler handler) { 
    super.onPostExecute(handler); 
    if (progBar != null && progBar.getVisibility() == View.VISIBLE) { 
     progBar.setVisibility(View.INVISIBLE); 
    } else if (mDialog != null && mDialog.isShowing()) { 
     try { 
      mDialog.dismiss(); 
     } catch (Exception e) { 
     } 
    } 
} 

修訂崩潰日誌:

12-20 15:19:15.802 :E/AndroidRuntime(9529):
android.view.WindowManager $壞TokenException:無法添加窗口 - 令牌[email protected]無效;您的活動 正在運行? 12-20 15:19:15.802:E/AndroidRuntime(9529):在 android.view.ViewRootImpl.setView(ViewRootImpl.java:567)12-20 15:19:15.802:E/AndroidRuntime(9529):在 android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:246) 12-20 15:19:15.802:E/AndroidRuntime(9529):在 android.view.WindowManagerImpl.addView(WindowManagerImpl.java:69) 12 -20 15:19:15.802:E/AndroidRuntime(9529):at android.app.Dialog.show(Dialog.java:281)12-20 15:19:15.802: E/AndroidRuntime(9529):at 下載AsyncTask $ 2.run(DownloadAsyncTask.java:119)12-20 15:19:15.802:E/AndroidRuntime(9529):at android.os.Handler.handleCallback(Handler.java:725)12- 20 15:19:15.802:E/AndroidRuntime(9529):at android.os.Handler.dispatchMessage(Handler.java:92)12-20 15:19:15.802:E/AndroidRuntime(9529):at android .os.Looper.loop(Looper.java:137)12-20 15:19:15.802: E/AndroidRuntime(9529):at android.app.ActivityThread.main(ActivityThread.java:5039)12-20 15:19:15.802:E/AndroidRuntime(9529):在 java.lang.reflect.Method.invokeNative(Native Method)12-20 15:19:15.802:E/AndroidRuntime(9529):在 java.lang .reflect.Method.invoke(Method.java:511)12-20 15:19:15.802: E/AndroidRuntime(9529):at com.android.internal.os.ZygoteInit $ MethodAndArgsCaller.run

+2

請發佈堆棧跟蹤,以顯示異常及其來源,以便我們能夠更好地告知您您做錯了什麼。 – CommonsWare

+0

它並不經常發生。我沒有地方保存日誌文件... 119 –

+0

線路是:@覆蓋 \t \t \t \t \t \t公共無效的run(){ \t \t \t \t \t \t \t mDialog.setMessage(mDialogMessage); \t \t \t \t \t mDialog.show(); \t \t \t \t \t \t –

回答

1

您接觸從後臺線程的用戶界面。 Android在技術上說「不更新」,但最好將其解讀爲「不要在後臺線程上與UI進行交互」。你if聲明實際上是說:「如果(...)是真的對UI,發佈這個任務要在UI線程上在一些在未來的時間執行」。在UI線程上執行Runnable時,UI的狀態可能已更改。封裝整個邏輯並將其發佈到要執行的UI線程可能會更好。您可以通過將兩個Runnable組合起來,並在一個post中發貨,但AsyncTask的設計使您無需直接處理處理程序。如果您在doInBackGround中調用publishProgress(),它將在UI線程上發出一個呼叫給onProgressUpdate()成員。因此,更簡單的做法是將Runnable中的代碼組合起來,然後轉到onProgressUpdate()方法。

喜歡的東西 -

void onProgressUpdate() { 
      if (mProgressBar != null && mProgressBar.getVisibility() == View.INVISIBLE) { 
       mProgressBar.setVisibility(View.VISIBLE); 
      } else if (mDialog != null && !mDialog.isShowing()) { 
       mDialog.setMessage(mDialogMessage); 
       mDialog.show(); 
      } 
     } 
+0

確定。這看起來更好一些。 –

0

使用runOnUiThread(可運行),以避免崩潰:這基本上運行在UI線程的run方法的代碼段。將下面顯示的所有要在run方法中執行的UI操作進行包裝。

所以代碼會去是這樣的:

yourActivity.runOnUiThread(新的Runnable(){

  @Override 
      public void run() { 
       // whatever UI operations.. 
       .. 
       mDialog.setMessage(mDialogMessage); 
       mDialog.show(); 
      } 

});

+0

您可以將該方法連接到正在生成狀態更新的AsyncTask嗎? –

+0

是的,我們可以! AsyncTask基本上是一個在bg線程中執行的任務。因此,在onPostExecute中,我們可以使用這種方法! –

相關問題