09-17 23:03:38.954: E/WindowManager(1994): android.view.WindowLeaked: Activity app.ui.MainActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView{b2d3d4e0 V.E..... R.....I. 0,0-280,139} that was originally added here
09-17 23:03:38.954: E/WindowManager(1994): at android.view.ViewRootImpl.<init>(ViewRootImpl.java:348)
09-17 23:03:38.954: E/WindowManager(1994): at android.view.WindowManagerGlobal.addView(WindowManagerGlobal.java:248)
09-17 23:03:38.954: E/WindowManager(1994): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:69)
09-17 23:03:38.954: E/WindowManager(1994): at android.app.Dialog.show(Dialog.java:286)
09-17 23:03:38.954: E/WindowManager(1994): at app.ui.MainActivity.showExitDialog(MainActivity.java:69)
09-17 23:03:38.954: E/WindowManager(1994): at app.ui.MainActivity.onKeyDown(MainActivity.java:48)
09-17 23:03:38.954: E/WindowManager(1994): at android.view.KeyEvent.dispatch(KeyEvent.java:2640)
09-17 23:03:38.954: E/WindowManager(1994): at android.app.Activity.dispatchKeyEvent(Activity.java:2423)
09-17 23:03:38.954: E/WindowManager(1994): at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:1962)
09-17 23:03:38.954: E/WindowManager(1994): at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3418)
09-17 23:03:38.954: E/WindowManager(1994): at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3558)
09-17 23:03:38.954: E/WindowManager(1994): at android.view.ViewRootImpl$ImeInputStage.onFinishedInputEvent(ViewRootImpl.java:3718)
09-17 23:03:38.954: E/WindowManager(1994): at android.view.inputmethod.InputMethodManager$PendingEvent.run(InputMethodManager.java:2010)
09-17 23:03:38.954: E/WindowManager(1994): at android.view.inputmethod.InputMethodManager.invokeFinishedInputEventCallback(InputMethodManager.java:1704)
09-17 23:03:38.954: E/WindowManager(1994): at android.view.inputmethod.InputMethodManager.finishedInputEvent(InputMethodManager.java:1695)
09-17 23:03:38.954: E/WindowManager(1994): at android.view.inputmethod.InputMethodManager$ImeInputEventSender.onInputEventFinished(InputMethodManager.java:1987)
09-17 23:03:38.954: E/WindowManager(1994): at android.view.InputEventSender.dispatchInputEventFinished(InputEventSender.java:141)
09-17 23:03:38.954: E/WindowManager(1994): at android.os.MessageQueue.nativePollOnce(Native Method)
09-17 23:03:38.954: E/WindowManager(1994): at android.os.MessageQueue.next(MessageQueue.java:138)
09-17 23:03:38.954: E/WindowManager(1994): at android.os.Looper.loop(Looper.java:123)
09-17 23:03:38.954: E/WindowManager(1994): at android.app.ActivityThread.main(ActivityThread.java:5017)
09-17 23:03:38.954: E/WindowManager(1994): at java.lang.reflect.Method.invokeNative(Native Method)
09-17 23:03:38.954: E/WindowManager(1994): at java.lang.reflect.Method.invoke(Method.java:515)
09-17 23:03:38.954: E/WindowManager(1994): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
09-17 23:03:38.954: E/WindowManager(1994): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
09-17 23:03:38.954: E/WindowManager(1994): at dalvik.system.NativeStart.main(Native Method)
首先说明:这个错误不属于内存溢出,而是android中的窗体溢出。
1.Activity 的生命周期与 Dialog 的不一样 AlertDialog.Builder builder=new AlertDialog.Builder(context);
2.这个context 是Activity的上下文
3.Dialog 要在Activity 销毁前 dismiss()掉,不然就窗体溢出
所以在解决此问题时,要判断窗体是否关闭,再干掉Activity
/**
* 捕获返回按钮事件
*/
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
showExitDialog();
return false;
} else {
return super.onKeyDown(keyCode, event);
}
}
//退出提示
protected void showExitDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("提示");
builder.setMessage("您确定要退出么?");
builder.setNegativeButton("取消", null);
builder.setPositiveButton("退出", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
MainActivity.this.finish();
dialog.cancel();//取消dialog,或dismiss掉
}
});
if (!isFinishing()) {
builder.create().show();
}
}
原因:Android的每一个Activity都有个WindowManager窗体管理器,同样,构建在某个Activity之上的对话框、PopupWindow也有相应的WindowManager窗体管理器。但是它们不能脱离Activity而单独存在着,因为需要Activity的Context,所以当某个Dialog或者某个PopupWindow正在显示的时候我们干掉了承载该Dialog(或PopupWindow)的Activity,就会抛Window Leaked异常了,因为这个Dialog(或PopupWindow)的WindowManager已经没有谁可以附属了(Context)。
在android中常常会遇到与context有关的内容,浅论一下context : 在语句 AlertDialog.Builder builder = new AlertDialog.Builder(this); 中,要求传递的参数就是一个context,在这里传入的是this,那么这个this究竟指的是什么东东呢? 这里的this指的是Activity.this,是当前这个Activity 的上下文(Context)。
网上有很多朋友在这里传入this.getApplicationContext(),这是不对的。为什么? AlertDialog对象是依赖于一个View的,而View是和一个Activity对应的。 于是,这里涉及到一个生命周期的问题,this.getApplicationContext()取的是整个应用程序的Context,Activity.this取的是这个Activity的Context,这两者的生命周期是不同 的,前者的生命周期是整个应用,后者的生命周期只是它所在的Activity。而AlertDialog应该是属于一个Activity的,在Activity销毁的时候它也就销毁了,不会再存在;但是,如果传入this.getApplicationContext(),就表示它的生命周期是整个应用程序,这显然超过了它 的生命周期了。
所以,在这里只能使用Activity的this。 差别就是不同的生命周期。