2011-07-07 110 views
40

我正在使用ProgressDialog來阻止用戶在設備從互聯網下載內容時進行交互。ProgressDialog:如何防止泄漏窗口

"07-06 17:10:50.363: ERROR/WindowManager(8821): Activity android.pixelrain.framework.PixelRainActivity has leaked window [email protected] that was originally added here 
07-06 17:10:50.363: ERROR/WindowManager(8821): android.view.WindowLeaked: Activity android.pixelrain.framework.PixelRainActivity has leaked window [email protected] that was originally added here 
07-06 17:10:50.363: ERROR/WindowManager(8821):  at android.view.ViewRoot.<init>(ViewRoot.java:251) 
07-06 17:10:50.363: ERROR/WindowManager(8821):  at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:148) 
07-06 17:10:50.363: ERROR/WindowManager(8821):  at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91) 
07-06 17:10:50.363: ERROR/WindowManager(8821):  at android.view.Window$LocalWindowManager.addView(Window.java:424) 
07-06 17:10:50.363: ERROR/WindowManager(8821):  at android.app.Dialog.show(Dialog.java:241) 
07-06 17:10:50.363: ERROR/WindowManager(8821):  at android.app.ProgressDialog.show(ProgressDialog.java:107) 
07-06 17:10:50.363: ERROR/WindowManager(8821):  at android.app.ProgressDialog.show(ProgressDialog.java:90) 
07-06 17:10:50.363: ERROR/WindowManager(8821):  at android.pixelrain.HTTPHelper.DraftHelper.getDraft(DraftHelper.java:70) 
07-06 17:10:50.363: ERROR/WindowManager(8821):  at android.pixelrain.online.OnlineRetriver.getDraft(OnlineRetriver.java:312) 
07-06 17:10:50.363: ERROR/WindowManager(8821):  at android.pixelrain.HTTPHelper.DraftButtonGL.loadDraft(DraftButtonGL.java:72) 
07-06 17:10:50.363: ERROR/WindowManager(8821):  at android.pixelrain.HTTPHelper.DraftButtonGL.isTouched(DraftButtonGL.java:89) 
07-06 17:10:50.363: ERROR/WindowManager(8821):  at android.pixelrain.opengl.views.game.QuickStartGL.touchEnded(QuickStartGL.java:160) 
07-06 17:10:50.363: ERROR/WindowManager(8821):  at android.pixelrain.game.GameHandler.onTouchEvent(GameHandler.java:277) 
07-06 17:10:50.363: ERROR/WindowManager(8821):  at android.pixelrain.opengl.GLSurfaceViewChipmunk.onTouchEvent(GLSurfaceViewChipmunk.java:27) 
07-06 17:10:50.363: ERROR/WindowManager(8821):  at android.view.View.dispatchTouchEvent(View.java:3765) 
07-06 17:10:50.363: ERROR/WindowManager(8821):  at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:944) 
07-06 17:10:50.363: ERROR/WindowManager(8821):  at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:944) 
07-06 17:10:50.363: ERROR/WindowManager(8821):  at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:944) 
07-06 17:10:50.363: ERROR/WindowManager(8821):  at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:1701) 
07-06 17:10:50.363: ERROR/WindowManager(8821):  at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1116) 
07-06 17:10:50.363: ERROR/WindowManager(8821):  at android.app.Activity.dispatchTouchEvent(Activity.java:2093) 
07-06 17:10:50.363: ERROR/WindowManager(8821):  at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:1685) 
07-06 17:10:50.363: ERROR/WindowManager(8821):  at android.view.ViewRoot.handleMessage(ViewRoot.java:1802) 
07-06 17:10:50.363: ERROR/WindowManager(8821):  at android.os.Handler.dispatchMessage(Handler.java:99) 
07-06 17:10:50.363: ERROR/WindowManager(8821):  at android.os.Looper.loop(Looper.java:144) 
07-06 17:10:50.363: ERROR/WindowManager(8821):  at android.app.ActivityThread.main(ActivityThread.java:4937) 
07-06 17:10:50.363: ERROR/WindowManager(8821):  at java.lang.reflect.Method.invokeNative(Native Method) 
07-06 17:10:50.363: ERROR/WindowManager(8821):  at java.lang.reflect.Method.invoke(Method.java:521) 
07-06 17:10:50.363: ERROR/WindowManager(8821):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868) 
07-06 17:10:50.363: ERROR/WindowManager(8821):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626) 
07-06 17:10:50.363: ERROR/WindowManager(8821):  at dalvik.system.NativeStart.main(Native Method)" 

,我不知道如何解決這一問題:直到我的客戶管理,以產生這種錯誤

一切工作正常。

任何想法是什麼原因造成的,以及如何解決它?

日誌追溯錯誤這一行:

progressDialog = ProgressDialog.show(PixelRainActivity.staticThis, "",PixelRainActivity.staticThis.getResources().getString(R.string.draftProgressMessage), true); 

會,如果我把它改成這樣就解決了這個問題:

this.runOnUiThread(new Runnable() { 
      public void run() { 
       progressDialog = ProgressDialog.show(PixelRainActivity.staticThis, "",PixelRainActivity.staticThis.getResources().getString(R.string.draftProgressMessage), true); 
      } 
     }); 
+2

我有同樣的問題,它只發生在活動暫停時打開'Dialog' /'ProcessDialog'時。是這樣嗎? – Wroclai

+1

或者可能在改變方向的同時? –

+0

請更新接受的答案是使用'dismiss' – yonix

回答

15

泄漏可能來自您的PixelRainActivity.staticThis屬性。如果您保留對某個活動的引用,即使此活動已被破壞,您仍然有內存泄漏。

修復的最簡單方法是使用應用程序的Context代替。在方法onCreate()更改staticThis = thisstaticThis = this.getApplicationContext(),它應該工作(和變化staticThis類型Context這是不是已經是這樣了)

+19

沒有爲我工作。我在異步任務的onPreExecute()中使用progressDialog.show()。我得到:android.view.WindowManager $ BadTokenException:無法添加窗口 - 標記null不適用於應用程序 – usman

+0

如果什麼都不起作用,請使用try/catch避免應用程序崩潰。 – usman

+14

爲了創建對話框,您必須傳遞不是上下文,而是傳遞活動。所以,this.getApplicationContext()不正確 –

1

而不是使用ProgressDialog.show()的,請嘗試使用

Activity.showDialog()它應該爲你自動管理Dialog並防止泄漏。

編輯:當你打電話showDialog(int),就會引發Activity.onCreateDialog(int)在那裏你可以創建Dialog你想和返回Dialog要顯示。

+1

但是我需要將一個ID傳遞給一個對話框,然後如何顯示進度對話框? –

+11

更新:此方法現已貶低!!! – PravinDodia

2

天鵝有權使用的ShowDialog(MY_INT),其中MY_INT是個好主意只是你選擇的一些常數值,只是爲了將它與其他類似的對話框區分開來。你可以用dismissDialog(MY_INT)以相同的方式取下它。只是不要從你的onPause方法啓動它。您可能希望從用戶將要使用的活動的onResume方法中執行此操作。然後你重寫像這樣的活動的onCreateDialog方法:

@Override 
protected Dialog onCreateDialog(int id) { 
    if(id == MY_INT) { 
     ProgressDialog progressDialog = new ProgressDialog(this); 
     progressDialog.setMessage("Your message string"); 
     return progressDialog; 
    } 
    return super.onCreateDialog(id); 
} 
101

用途:

progressDialog.dismiss(); 

在結束工作

+0

請使這個接受的答案,並節省我們所有的時間... – yonix

0

如果您正在使用的任何threadAsyncTask,並從互聯網上下載的東西,並顯示progress bar,你應該使用DialogFragment或取消進度dialogActivity得到停止,如果你正在顯示進度Asynctask拳頭取消Asynctask並覆蓋oncancel回調方法和dismiss進度對話。

Window leakActivityfragment實際發生是由於你正在嘗試添加窗口,雖然它顯示了它在​​,但是當你按下它被暫停的回家,然後被通過onStop停止( )。所以你的CustomView仍然連接到現在已經消失的窗口。因此根據系統,您的customView佔用了它沒有釋放的空間。

0

它更好地使用AsyncTask從互聯網上獲取東西在後臺。而且不需要傳遞靜態上下文。而活動

new YourAsyncTask(context).execute(); 

呼叫的AsyncTask像上面

private class YourAsynTask extends AsyncTask<String,Void,String> 
{ 
private Context context; 
private ProgressDialog progressDialog; 

//pass context in constructor 
    public YourAsynTask(Context context) 
    { 
    this.context = context; 
    } 

    //show progress in onPre 
    @Override 
    protected void onPreExecute() 
    { 
    //show Progress code here. 
    progressDialog = ProgressDialog.show(context, "", "Loading. Please wait...", true); 
    } 

    //dismiss Progress dialog in onPost 
    @Override 
    protected void OnPostExecute(String response) 
    { 
    if(progressDialog!=null) 
    progressDialog.dismiss(); 
    progressDialog = null; 
    } 
} 
1

當你有onDetachonDestroy以驗證進度對話框仍可見有一些情況。 像這樣:

@Override 
public void onDetach() { 
    if (mProgressDialog != null && mProgressDialog.isShowing()) 
     mProgressDialog.dismiss(); 
    super.onDetach(); 
} 
0

嘗試調用progressDialog.dismiss()活動就會被殺死了。我得到了這樣的固定。