2012-08-29 73 views
1

我正嘗試將iPhone應用程序移植到Android,但遇到一些啓動困難。嘗試顯示警告對話框時泄漏窗口

我有以下函數來獲取數據:

public void onClick(View v) { 
     try{ 
      //Toast.makeText(getApplicationContext(), "Starting update", Toast.LENGTH_SHORT).show(); 
      progressDialog = ProgressDialog.show(MainActivity.this, "", "Loading..."); 
      new Thread() { 
       public void run() { 
        try{ 
         DataManager manager = new DataManager(getApplicationContext()); 
         manager.updateData(); 
        } catch (Exception e) { 
         Log.e(TAG, e.getMessage()); 

         AlertDialog alertDialog = new AlertDialog.Builder(MainActivity.this).create(); 
         alertDialog.setTitle("Error..."); 
         alertDialog.setMessage(e.getMessage()); 
         alertDialog.show(); 
        } 
        progressDialog.dismiss(); 
       } 
      }.start(); 
     } catch (Exception e) { 
      Log.e(TAG, "Problem with getting the data: " + e.getMessage()); 
      Toast.makeText(getApplicationContext(), "Error during update", 
        Toast.LENGTH_SHORT).show(); 
     } 

    } 

但是,如果出現異常,我得到以下錯誤(我最初嘗試使用的AsyncTask,但遇到了同樣的問題):

08-29 20:23:24.389: ERROR/WindowManager(974): Activity org.idoms.iDomsAndroid.MainActivity has leaked window [email protected] that was originally added here 
     android.view.WindowLeaked: Activity org.idoms.iDomsAndroid.MainActivity has leaked window [email protected] that was originally added here 
     at android.view.ViewRootImpl.<init>(ViewRootImpl.java:344) 
     at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:267) 
     at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:215) 
     at android.view.WindowManagerImpl$CompatModeWrapper.addView(WindowManagerImpl.java:140) 
     at android.view.Window$LocalWindowManager.addView(Window.java:537) 
     at android.app.Dialog.show(Dialog.java:278) 
     at android.app.ProgressDialog.show(ProgressDialog.java:116) 
     at android.app.ProgressDialog.show(ProgressDialog.java:99) 
     at android.app.ProgressDialog.show(ProgressDialog.java:94) 
     at org.idoms.iDomsAndroid.MainActivity$1.onClick(MainActivity.java:46) 
     at android.view.View.performClick(View.java:3511) 
     at android.view.View$PerformClick.run(View.java:14105) 
     at android.os.Handler.handleCallback(Handler.java:605) 
     at android.os.Handler.dispatchMessage(Handler.java:92) 
     at android.os.Looper.loop(Looper.java:137) 
     at android.app.ActivityThread.main(ActivityThread.java:4424) 
     at java.lang.reflect.Method.invokeNative(Native Method) 
     at java.lang.reflect.Method.invoke(Method.java:511) 
     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784) 
     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551) 
     at dalvik.system.NativeStart.main(Native Method) 

什麼是正確的方法來做到這一點?

+0

正如@Willie Tsang所說 - 你不能與主(UI)線程交互。返回使用'AsyncTask',如果發生錯誤,請'doInBackground(...)'返回某種'失敗'結果。這將被傳遞給'AsyncTask'的'onPostExecute(...)'方法,當它在主(UI)線程上運行時,它將能夠顯示'AlertDialog'。 – Squonk

回答

1

我的猜測是,線程無法與主UI線程元素進行交互。

progressDialog是在主Ui線程中創建的,其他線程無法與其交互。你可以在字段中給它一個信號並檢查它的進度,但我真的會推薦使用Asynctask來完成這個任務。

AsyncTask

0

UI元素(如一個AlertDialog)只能從主(UI)線程來操縱。如果你試圖從後臺線程中操作它們(這就是你正在做的new Thread() { ... }),你會得到這個異常。

你可以通過調用runOnUiThread(new Runnable() { ... });訪問AlertDialogprogressDialog的時候解決這個問題,但這是非常,非常,非常髒

更好的解決方案是使用AsyncTask(或更好的AsyncTaskLoader,因爲它需要照顧方位變化和其他一些東西)。使用AsyncTask時,確保不是訪問doInBackground()-方法中的UI元素。作爲名稱,saysdoInBackground(...)在後臺線程中執行。如果您嘗試使用該方法處理UI元素,那麼您現在確實會遇到同樣的錯誤。如果要從AsyncTask訪問UI元素,可以在onPreExecute(...),onProgressUpdate(...)onPostExecute(...)方法中執行。

0

窗口泄漏的原因是由於您的alertDialog在應用程序關閉前未被解除。