活动泄漏了最初添加的窗口

这个错误是什么,为什么会发生?

05-17 18:24:57.069: ERROR/WindowManager(18850): Activity com.mypkg.myP has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@44c46ff0 that was originally added here 05-17 18:24:57.069: ERROR/WindowManager(18850): android.view.WindowLeaked: Activity ccom.mypkg.myP has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@44c46ff0 that was originally added here 05-17 18:24:57.069: ERROR/WindowManager(18850): at android.view.ViewRoot.<init>(ViewRoot.java:231) 05-17 18:24:57.069: ERROR/WindowManager(18850): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:148) 05-17 18:24:57.069: ERROR/WindowManager(18850): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91) 05-17 18:24:57.069: ERROR/WindowManager(18850): at android.view.Window$LocalWindowManager.addView(Window.java:424) 05-17 18:24:57.069: ERROR/WindowManager(18850): at android.app.Dialog.show(Dialog.java:239) 05-17 18:24:57.069: ERROR/WindowManager(18850): at com.mypkg.myP$PreparePairingLinkageData.onPreExecute(viewP.java:183) 05-17 18:24:57.069: ERROR/WindowManager(18850): at android.os.AsyncTask.execute(AsyncTask.java:391) 05-17 18:24:57.069: ERROR/WindowManager(18850): at com.mypkg.myP.onCreate(viewP.java:94) 05-17 18:24:57.069: ERROR/WindowManager(18850): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047) 05-17 18:24:57.069: ERROR/WindowManager(18850): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2544) 05-17 18:24:57.069: ERROR/WindowManager(18850): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2621) 05-17 18:24:57.069: ERROR/WindowManager(18850): at android.app.ActivityThread.access$2200(ActivityThread.java:126) 05-17 18:24:57.069: ERROR/WindowManager(18850): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1932) 05-17 18:24:57.069: ERROR/WindowManager(18850): at android.os.Handler.dispatchMessage(Handler.java:99) 05-17 18:24:57.069: ERROR/WindowManager(18850): at android.os.Looper.loop(Looper.java:123) 05-17 18:24:57.069: ERROR/WindowManager(18850): at android.app.ActivityThread.main(ActivityThread.java:4595) 05-17 18:24:57.069: ERROR/WindowManager(18850): at java.lang.reflect.Method.invokeNative(Native Method) 05-17 18:24:57.069: ERROR/WindowManager(18850): at java.lang.reflect.Method.invoke(Method.java:521) 05-17 18:24:57.069: ERROR/WindowManager(18850): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860) 05-17 18:24:57.069: ERROR/WindowManager(18850): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618) 05-17 18:24:57.069: ERROR/WindowManager(18850): at dalvik.system.NativeStart.main(Native Method) 

在退出活动后,您正试图显示一个对话框。

[编辑]

这个问题是Android开发人员的谷歌最热门的search之一,因此,从评论添加一些重要的点,这可能会更有助于未来的调查,而不会深入的评论对话。

答案1

在退出活动后,您正试图显示一个对话框。

答案2

这个错误在某些情况下可能有些误导(尽pipe答案仍然是完全准确的) – 即在我的情况下,在AsyncTask中引发了一个未处理的Exception,导致Activityclosures,然后一个打开的progressdialog导致这个exception。日志中的“真正”例外情况稍早

答案3

在退出Activity之前创build的Dialog实例上调用dismiss(),例如在onPause()或onDestroy()

解决方法是在退出Activity之前,在viewP.java:183创build的Dialog调用dismiss() ,例如在onPause() 。 所有的WindowDialog应该在离开Activity之前closures。

如果您使用的是AsyncTask ,那么这个日志消息可能是骗人的。 如果你在你的日志中查找,你可能会发现另一个错误,可能是你的AsyncTask doInBackground()方法中的一个错误,使得你的当前Activity被炸毁,因此一旦AsyncTask回来,rest。 其他一些用户已经在这里解释:-)

你可以通过一个简单/愚蠢的错误,例如,在显示AlertDialog后意外地调用finish() ,如果你在switch语句中错过了一个break调用语句来得到这个exception…

  @Override public void onClick(View v) { switch (v.getId()) { case R.id.new_button: openMyAlertDialog(); break; <-- If you forget this the finish() method below will be called while the dialog is showing! case R.id.exit_button: finish(); break; } } 

finish()方法将closuresActivity ,但AlertDialog仍在显示!

所以当你专注于代码,寻找不好的线程问题或复杂的编码等,不要忽略了树木的森林。 有时,它可能只是一个简单和愚蠢的失踪断言。 🙂

我通过在AlertDialog上错误地调用hide()而不是dismiss()来触发这个错误。

尝试在退出活动后显示对话框时出现此问题。

我只是写下下面的代码就解决了这个问题:

 @Override public void onDestroy(){ super.onDestroy(); if ( progressDialog!=null && progressDialog.isShowing() ){ progressDialog.cancel(); } } 

基本上,你从哪个类开始progressDialog,重写onDestroy方法,这样做。 它解决了“活动漏窗”的问题。

我最近面临同样的问题。

这个问题背后的原因是在对话被解散之前活动被closures。 发生上述情况有多种原因。 在上面的post中提到的也是正确的。

我陷入了一种情况,因为在线程中,我正在调用一个抛出exception的函数。 正因为如此,窗户被解雇,因此是例外。

我有相同的晦涩的错误信息,不知道为什么。 鉴于从以前的答案线索,我改变我的非GUI调用mDialog.finish()是mDialog.dismiss()和错误消失。 这并不影响我的小部件的行为,但这是令人不安的,可能已经标记了一个重要的内存泄漏。

我有同样的问题,发现这个网页,而我的情况是不同的,我叫一个if块完成之前,它定义了警报框。 所以简单地打电话解雇将不起作用(因为它还没有做),但在阅读亚历克斯Volovoy的答案,并意识到这是警报框造成它我试图添加一个返回语句后,完成内部,如果块和解决了这个问题。 我想,一旦你打完了,就停止了一切,并在那里完成。 但它并没有,它似乎完成了代码块的结束。 所以如果你想实现一个情况,有时它会在做一些代码之前完成,你必须在完成之后立即返回一个return语句,否则它将继续执行,并且在结束时调用完成的代码不在你叫它的地方。 这就是为什么我得到所有这些奇怪的错误。

 private picked(File aDirectory) { if(aDirectory.length()==0){setResult(RESULT_CANCELED, new Intent()); finish(); return;} AlertDialog.Builder alert= new AlertDialog.Builder(this); // Start dialog builder alert.setTitle("Question").setMessage("Do you want to open that file?"+aDirectory.getName()); alert.setPositiveButton("OK", okButtonListener).setNegativeButton("Cancel", cancelButtonListener); alert.show(); } 

如果你在我打完电话之后没有把这个回报放在那里,就会像在alert.show();之后调用它alert.show(); 因此,我说我在对话出现之后就完成了窗口的泄漏,尽pipe事实并非如此。 我想我会在这里添加这个,因为这表明完成命令的行为不同,然后我认为它做了,我猜想还有其他人像我之前发现的一样思考。

我在我的video播放器应用程序中获取这些日志。 video播放器closures时,这些消息被抛出。 有趣的是,我曾经以随机的方式在一些运行中得到这些日志。 另外我的应用程序不涉及任何progressdialog 。 最后,我用下面的实现来解决这个问题。

 @Override protected void onPause() { Log.v("MediaVideo", "onPause"); super.onPause(); this.mVideoView.pause(); this.mVideoView.setVisibility(View.GONE); } @Override protected void onDestroy() { Log.v("MediaVideo", "onDestroy"); super.onDestroy(); } @Override protected void onResume() { Log.v("MediaVideo", "onResume"); super.onResume(); this.mVideoView.resume(); } 

通过调用mVideoView.pause()并设置GONE visibility来覆盖OnPause 。 这样我可以解决“ Activity has leaked window ”日志错误问题。

活动破坏时closures对话框

 @Override protected void onDestroy() { super.onDestroy(); if (pDialog!=null && pDialog.isShowing()){ pDialog.dismiss(); } } 

这可能有帮助。

 if (! isFinishing()) { dialog.show(); } 

不仅试图显示一个警报,但它可以调用,当你完成一个特定的活动实例,并尝试开始新的活动,服务或停止它..例如..

 OldActivity instance; oncreate() { instance=this; } instance.finish(); instance.startActivity(new Intent(ACTION_MAIN).setClass(instance, NewActivity.class)); 

这不是问题的答案,而是与主题相关。

如果活动在Manifest中定义了一个属性

  android:noHistory="true" 

那么执行onPause()之后,活动的上下文就会丢失。 所以所有的视图使用这个上下文可能会给这个错误。

这可以是,如果你在doInBackground()函数有一个错误,并有此代码。

最后尝试添加对话框。 首先检查并修复doInBackground()函数

 protected void onPreExecute() { super.onPreExecute(); pDialog = new ProgressDialog(CreateAccount.this); pDialog.setMessage("Creating Product.."); pDialog.setIndeterminate(false); pDialog.setCancelable(true); pDialog.show(); } protected String doInBackground(String...args) { ERROR CAN BE IS HERE } protected void onPostExecute(String file_url) { // dismiss the dialog once done pDialog.dismiss(); 

Activity有效finished后,当您尝试显示警报时,会发生“ Activity has leaked window that was originally added... ”错误。

你有两个selectAFAIK:

  1. 反思您的警报login:在实际退出您的活动之前,请在dialog调用dismiss()
  2. dialog放在不同的线程中,并在该thread上运行(与当前activity无关)。

有ProgressDialog仍显示时,我完成一个活动的问题。

所以首先隐藏对话框,然后完成活动。

试试这个代码:

 public class Sample extends Activity(){ @Override public void onCreate(Bundle instance){ } @Override public void onStop() { super.onStop(); progressdialog.dismiss(); // try this } } 

这发生在我身上,当我在AsyncTask使用ProgressDialog 。 其实我在onPostExecute使用hide()方法。 根据@Alex Volovoy的回答,我需要使用dismiss()ProgressDialog在onPostExecute中将其删除。

 progressDialog.hide(); // Don't use it, it gives error progressDialog.dismiss(); // Use it 

您必须在AsyncTask onPreExecute方法中创buildProgressdialog对象,并且您应该dismiss onPostExecute方法。

在我的情况下,原因是我忘记了在Android清单文件中包含权限。

我怎么知道的? 好吧,就像@Bobby在接受的答案下面的评论中所说的那样,只要进一步向上滚动到你的日志,你就会看到第一个真正抛出Exception的原因或事件。 显然,消息“活动泄漏了最初添加的窗口”仅仅是一个exception,无论第一个exception是什么。

尝试下面的代码,它将工作任何时候你会解雇的进展对话,它会看到它的实例是否可用。

 try { if (null != progressDialog && progressDialog.isShowing()) { progressDialog.dismiss(); progressDialog = null; } } catch (Exception e) { e.printStackTrace(); } 

这个问题的答案都是正确的,但是让我有点困惑的是要真正理解为什么。 玩了大约2个小时后,这个错误的原因(在我的情况)打我:

你已经知道,从阅读其他答案,已经X has leaked window DecorView@d9e6131[]错误意味着一个对话框已经打开,当你的应用程序closures。 但为什么?

这可能是,你的应用程序在打开对话框时出于其他原因而崩溃

这会导致您的应用程序因为您的代码中的一些错误而closures,导致在您的应用程序由于其他错误而closures的同时保持打开对话框。

所以,看看你的逻辑。 解决第一个错误,然后第二个错误将自行解决 在这里输入图像描述

一个错误会导致另一个错误,如DOMINOS!

只要确保您的活动没有意外closures,因为在代码中某处引发了一些exception。 当doinBackground方法中的活动面向强制closures时,通常发生在asynchronous任务中,然后asynchronous请求返回到onPostexecute方法。

窗口泄漏exception有两个原因:

1)当Activity Context不存在时显示对话框,解决这个问题你应该只显示对话框你确定Activity存在:

 if(getActivity()!= null && !getActivity().isFinishing()){ Dialog.show(); } 

2)没有正确解除对话框,解决使用此代码:

 @Override public void onDestroy(){ super.onDestroy(); if ( Dialog!=null && Dialog.isShowing() ){ Dialog.dismiss(); } } 

我有同样的问题。 该错误不是在Dialog而是在EditText 。 我试图改变一个Edittext里的Assynctask 。 唯一能解决的就是创build一个新的runnable

 runOnUiThread(new Runnable(){ @Override public void run() { ... } }); 

我正在使用一个video播放器的onError对话框,而不是发疯(我已经testing了所有这些解决scheme)

我select了DialogFragment http://developer.android.com/reference/android/app/DialogFragment.html

您可以在内部DialogFragment类中返回构build器创build,只需重写onCreateDialog

我有另一个解决scheme,并想知道它是否对您有用:而不是解雇onDestroy,这似乎是领先的解决scheme,我扩展ProgressDialog …

 public class MyProgressDialog extends ProgressDialog { private boolean isDismissed; public MyProgressDialog(Context context) { super(context); } @Override public void onDetachedFromWindow() { super.onDetachedFromWindow(); dismiss(); } @Override public void dismiss() { if (isDismissed) { return; } try { super.dismiss(); } catch (IllegalArgumentException e) { // ignore } isDismissed = true; } 

这是可取的,AFAIC,因为你不必把进度对话框作为一个成员,只是射击(显示),忘记

运行猴子testing时,我也遇到WindowLeaked问题。下面是logcat。

 android.support.v7.app.AppCompatDelegateImplV7$ListMenuDecorView@4334fd40 that was originally added here android.view.WindowLeaked: Activity com.myapp.MyActivity has leaked window android.support.v7.app.AppCompatDelegateImplV7$ListMenuDecorView@4334fd40 that was originally added here at android.view.ViewRootImpl.<init>(ViewRootImpl.java:409) at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:312) at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:224) at android.view.WindowManagerImpl$CompatModeWrapper.addView(WindowManagerImpl.java:149) at android.view.Window$LocalWindowManager.addView(Window.java:554) at android.support.v7.app.AppCompatDelegateImplV7.openPanel(AppCompatDelegateImplV7.java:1150) at android.support.v7.app.AppCompatDelegateImplV7.onKeyUpPanel(AppCompatDelegateImplV7.java:1469) at android.support.v7.app.AppCompatDelegateImplV7.onKeyUp(AppCompatDelegateImplV7.java:919) at android.support.v7.app.AppCompatDelegateImplV7.dispatchKeyEvent(AppCompatDelegateImplV7.java:913) at android.support.v7.app.AppCompatDelegateImplBase$AppCompatWindowCallbackBase.dispatchKeyEvent(AppCompatDelegateImplBase.java:241) at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:2009) at android.view.ViewRootImpl.deliverKeyEventPostIme(ViewRootImpl.java:3929) at android.view.ViewRootImpl.deliverKeyEvent(ViewRootImpl.java:3863) at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:3420) at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:4528) at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:4506) at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:4610) at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:171) at android.os.MessageQueue.nativePollOnce(Native Method) at android.os.MessageQueue.next(MessageQueue.java:125) at android.os.Looper.loop(Looper.java:124) at android.app.ActivityThread.main(ActivityThread.java:4898) 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:1008) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:775) at dalvik.system.NativeStart.main(Native Method) 

我的活动是AppCompatActivity.And我用下面的代码在活动中解决它。

 @Override public boolean dispatchKeyEvent(KeyEvent event) { // added by sunhang : intercept menu key to resove a WindowLeaked error in monkey-test. if (event.getKeyCode() == KeyEvent.KEYCODE_MENU) { return true; } return super.dispatchKeyEvent(event); } 
  if (mActivity != null && !mActivity.isFinishing() && mProgressDialog != null && mProgressDialog.isShowing()) { mProgressDialog.dismiss(); }