ProgressDialog:如何防止泄漏窗口
我正在使用 ProgressDialog 来防止用户在设备从互联网下载内容时进行交互。
一切都工作正常,直到我的客户设法产生这个错误:
"07-06 17:10:50.363: ERROR/WindowManager(8821): Activity android.pixelrain.framework.PixelRainActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@463f3e50 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 com.android.internal.policy.impl.PhoneWindow$DecorView@463f3e50 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);
}
});
I'm using ProgressDialog to prevent the user from interacting while the device is downloading stuff from internet.
everything was working fine until my client managed to produce this bug :
"07-06 17:10:50.363: ERROR/WindowManager(8821): Activity android.pixelrain.framework.PixelRainActivity has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@463f3e50 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 com.android.internal.policy.impl.PhoneWindow$DecorView@463f3e50 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)"
and I have no idea how to fix this.
any ideas what causes this and how to solve it ?
The log traces back the error to this line :
progressDialog = ProgressDialog.show(PixelRainActivity.staticThis, "",PixelRainActivity.staticThis.getResources().getString( R.string.draftProgressMessage), true);
would it solve the problem if I changed it to this :
this.runOnUiThread(new Runnable() {
public void run() {
progressDialog = ProgressDialog.show(PixelRainActivity.staticThis, "",PixelRainActivity.staticThis.getResources().getString( R.string.draftProgressMessage), true);
}
});
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(11)
用途:
最终工作
Use:
in end work
泄漏可能来自您的
PixelRainActivity.staticThis
属性。如果您保留对某个活动的引用,即使该活动已被销毁,也会发生内存泄漏。最简单的修复方法是使用应用程序的
Context
。将方法onCreate()
中的staticThis = this
行更改为staticThis = this.getApplicationContext()
并且它应该可以工作(并更改类型staticThis
到Context
(如果情况还不是这样)The leak comes probably from your
PixelRainActivity.staticThis
attribute. If you’re keeping a reference to an activity, even after that this activity has been destroyed, you have a memory leak.The easiest way to fix is to use the application’s
Context
instead. Change yourstaticThis = this
line in the methodonCreate()
tostaticThis = this.getApplicationContext()
and it should work (and change the type ofstaticThis
toContext
if this is not already the case)在某些情况下,您必须在
onDetach
或onDestroy
中验证进度对话框是否仍然可见。就像这样:
There are situations when you have to verify in
onDetach
or inonDestroy
if the progress dialog is still visible.Like so:
cygnus 有一个使用 showDialog(MY_INT) 的好主意,其中 MY_INT 只是您选择的一些常量值,只是为了将其与您以这种方式启动的任何其他类似对话框区分开来。您可以使用解雇对话框(MY_INT)以相同的方式将其删除。只是不要从 onPause 方法启动它。您可能希望通过用户将要进行的活动的 onResume 方法来执行此操作。然后您重写该活动的 onCreateDialog 方法,如下所示:
cygnus has a good idea to use showDialog(MY_INT), where MY_INT is just some constant value you choose just to distinguish it from any other similar dialogs you launch that way. You take it down the same way with dismissDialog(MY_INT). Just don't launch it from your onPause method. You may want to do that instead from the the onResume method of the activity the user is going to. Then you override that activity's onCreateDialog method like this:
不要使用
ProgressDialog.show()
,而是尝试使用Activity.showDialog()
,它会自动为您管理Dialog
并防止泄漏。编辑:当您调用
showDialog(int)
时,它将触发Activity.onCreateDialog(int)
,您可以在其中创建您想要的Dialog
并返回您想要显示的Dialog
。Instead of using
ProgressDialog.show()
, try usingActivity.showDialog()
which should automatically manage theDialog
for you and prevent leaks.EDIT: When you call
showDialog(int)
, it will triggerActivity.onCreateDialog(int)
where you can create theDialog
you want and return theDialog
you want to display.我在进度对话框和后台任务中遇到了类似的问题。 AsyncTask (http://android-developers.blogspot.de/2009/ 05/painless-threading.html)让我能够更干净地完成这两件事,并且没有泄漏的窗口。
I ran into a similar problem with a progress dialog and a background task. The AsyncTask (http://android-developers.blogspot.de/2009/05/painless-threading.html) allowed me to do both much more cleanly and without the leaked window.
最好使用
AsyncTask
在后台从互联网获取某些内容。不过,不需要传递静态上下文。和上面的 Activity 一样调用 AsyncTask
Its better to use an
AsyncTask
to get something from internet in the background. And there is no need to pass a static context though. And activityCall AsyncTask like above
如果您正在使用任何
thread
或AsyncTask
并从互联网下载内容并显示进度条
,您应该使用DialogFragment
或者当Activity
停止时取消进度dialog
,如果您在Asynctask
中显示进度,首先取消Asynctask
并覆盖< code>oncancel 回调方法和那里关闭
进度对话框。Activity
或fragment
中的Window Leak
实际上是由于您尝试添加一个窗口而发生的,而当它显示时,它位于>foreground
,但是当您按下 home 时,它会暂停,然后通过onStop
() 停止。因此,您的CustomView
仍然附加到现在已经消失的窗口。因此,根据系统,您的customView
占用了它没有释放的空间。If you are using any
thread
orAsyncTask
and downloading stuff from internet and showingprogress bar
, you should useDialogFragment
or cancel progressdialog
whenActivity
get stop also if you are showing progress inAsynctask
fist cancelAsynctask
and overrideoncancel
callback method anddismiss
progress dialogue there.Window leak
inActivity
orfragment
is actually occurs due to you are trying to add a window and while it shows up it is on theforeground
,but when you are pressing the home it gets paused and then gets stopped via theonStop
(). So yourCustomView
remains attached to the window that now has disappeared.Hence according to the system yourcustomView
occupied the space which it did not release.当另一个 Activity 进入前台时,只需调用 cancel() 方法即可。
Just call the cancel() method when another activity comes into the foreground.
我遇到了这个异常
这个修复对我有用:
I was gettin this exception
This fix worked for me:
尝试在 Activity 被终止之前调用
progressDialog.dismiss()
。我的就这样修好了Try calling
progressDialog.dismiss()
before the activity gets killed. I got mine fixed like this.