这是什么错误,为什么会发生?
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)
30 回答
如果您使用
AsyncTask
,可能该日志消息可能具有欺骗性 . 如果你在日志中查找,你可能会发现另一个错误,可能是AsyncTask
的doInBackground()
方法中的一个错误,这会使你当前的Activity
爆炸,因此一旦AsyncTask
回来了......好吧,你知道其余的 . 其他一些用户已在此处解释:-)在退出活动后尝试显示对话框时会出现此问题 .
我刚刚通过写下以下代码解决了这个问题:
基本上,从哪个类开始progressDialog,覆盖onDestroy方法并以这种方式执行 . 它解决了“活动已泄露窗口”的问题 .
如果仍然显示ProgressDialog,我在完成活动的问题 .
首先隐藏对话框,然后完成活动 .
在我的情况下,原因是我忘了在Android清单文件中包含权限 .
我是怎么知道的?好吧,就像@Bobby在接受的答案下面的评论中说的那样,只需向上滚动到你的日志,你就会看到真正抛出异常的第一个原因或事件 . 显然,消息“活动已泄漏最初添加的窗口”只是一个异常,它是由第一个异常引起的 .
这不是问题的答案,但它与该主题相关 .
如果活动在Manifest中定义了一个属性
然后在执行onPause()之后,活动的上下文就会丢失 . 因此,使用此上下文的所有视图都可能会出现此错误 .
我错误地在
AlertDialog
上调用hide()
而不是dismiss()
来触发此错误 .通常由于进度对话框而出现此问题:您可以通过在活动中使用以下任一方法来解决此问题:
如果您在
doInBackground()
函数中有错误并且拥有此代码,则可以这样做 .尝试最后添加对话框 . 首先检查并修复
doInBackground()
功能根据我的问题是你试图在一个活动完成后立即调用一个对话框,所以根据我你可以做的是使用Handler给你一些延迟,你的问题将被解决,例如:
您在退出活动后尝试显示对话框 .
[EDIT]
这个问题是google for android开发人员的热门搜索之一,因此在评论中添加了一些重要的观点,这可能对未来的调查人员更有帮助,而无需进行深入的评论对话 .
Answer 1 :
Answer 2
Answer 3
解决方法是在退出
Activity
之前在viewP.java:183
中创建的Dialog
上调用dismiss()
,例如在onPause()
. 所有Window
s&Dialog
应该在离开Activity
之前关闭 .我最近遇到了同样的问题 .
这个问题背后的原因是在关闭对话框之前关闭了活动 . 上述情况有多种原因 . 上面帖子中提到的那些也是正确的 .
我遇到了一个情况,因为在线程中,我正在调用一个抛出异常的函数 . 因为窗户被解雇,因此例外 .
我遇到了同样的问题并找到了这个页面,虽然我的情况不同,但在定义警告框之前,我从
if
块调用finish
.因此,简单地调用
dismiss
还没有制作完成)但是在阅读了Alex Volovoy的回答并意识到它是引起它的警报框之后 . 我试图在if
块内完成后立即添加一个return语句,并修复了问题 .我想过,一旦你叫完了它就停止了一切并在那里完成,但事实并非如此 . 它似乎已经完成了代码块的结尾 .
所以,如果你想要实现一种情况,有时它会在完成一些代码之前完成,你必须在完成之后立即放置一个return语句,否则它将继续运行并且就像在结束时调用结束一样 . 不在你调用它的地方的代码块 . 这就是为什么我得到了所有那些奇怪的错误 .
如果你在我在那里调完完之后没有把它放回去,那么就好像你在
alert.show();
之后调用它一样,因此它会说窗口被泄露了通过在对话框出现后完成,即使情况并非如此,它仍然认为是 .我以为我会在这里添加这个,因为这表明结束命令的行为不同然后我认为它确实如此,我猜其他人在我发现这个之前就像我一样 .
你可以通过一个简单/愚蠢的错误来获得这个异常,例如,如果你在switch语句中错过了一个中断调用语句,那么在显示
AlertDialog
之后意外调用了finish()
...finish()
方法将关闭Activity
,但AlertDialog
仍然显示!因此,当你专心盯着代码,寻找糟糕的线程问题或复杂的编码等时,不要忘记树木的森林 . 有时它可能只是一个简单而愚蠢的东西,就像一个缺失的断言 . :)
Best solution is just add dialog in try catch and dismiss dialog when exception occur
不仅尝试显示警报,还可以在完成特定活动实例并尝试启动新活动/服务或尝试停止时调用它 .
Example:
这可能有所帮助 .
这个问题的答案都是正确的,但对我来说实际理解为什么有点困惑 . 玩了大约2个小时后,这个错误的原因(在我的情况下)打了我:
通过阅读其他答案,您已经知道
X has leaked window DecorView@d9e6131[]
错误意味着当您的应用关闭时,对话框已打开 . 但为什么?It could be, that your app crashed for some other reason while your dialog was open
这导致您的应用关闭,因为您的代码中存在一些错误,导致对话框因应用程序因其他错误而关闭的同时保持打开状态 .
So, look through your logical. Solve the first error, and then the second error will solve itself
One error causes another, which causes another, like DOMINOS!
活动销毁时关闭对话框
由于代码中某处出现了一些异常,请确保您的活动未意外关闭 . 通常,当活动面临强制关闭doinBackground方法然后asynctask返回onPostexecute方法时,它发生在异步任务中 .
你必须在
AsyncTask
的onPreExecute
方法中创建Progressdialog
对象,你应该在onPostExecute
方法上dismiss
它 .我在我的视频播放器应用程序中获取这些日志 . 视频播放器关闭时抛出这些消息 . 有趣的是,我曾经以随机方式在几次运行中获取这些日志 . 我的申请也不涉及任何
progressdialog
. 最后,我通过以下实现解决了这个问题 .通过调用
mVideoView.pause()
覆盖OnPause
并将visibility
设置为GONE
. 这样我就可以解决“Activity has leaked window
”日志错误问题 .窗口泄露异常有两个原因:
1)当Activity Context不存在时显示对话框,要解决此问题,您应该只显示对话框,确定Activity存在:
2)不要适当地关闭对话框,解决使用此代码:
当我在
AsyncTask
中使用ProgressDialog
时,这发生在我身上 . 其实我在onPostExecute
中使用hide()
方法 . 根据@Alex Volovoy的答案,我需要使用dismiss()
和ProgressDialog
在onPostExecute中删除它并完成它 .最佳解决方案是在显示
progressbar
或progressDialog
之前我有同样晦涩的错误信息,不知道为什么 . 根据之前答案的线索,我将我的非GUI调用mDialog.finish()更改为mDialog.dismiss(),错误消失了 . 这并没有影响我的小部件的行为,但它令人不安,很可能已经标记了一个重要的内存泄漏 .
当
Activity
实际上是finished
后尝试显示警报时,会出现“Activity has leaked window that was originally added...
”错误 .你有两个选择AFAIK:
重新考虑警报的登录:在实际退出活动之前,在
dialog
上调用dismiss()
.将
dialog
放在另一个线程中并在thread
上运行它(与当前activity
无关) .尝试下面的代码,它将在您解除进度对话框的任何时候工作,它将查看其实例是否可用 .
试试这段代码: