ProgressDialog:如何防止泄漏窗口

发布于 2024-11-18 20:34:45 字数 4868 浏览 2 评论 0原文

我正在使用 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

惜醉颜 2024-11-25 20:34:45

用途:

progressDialog.dismiss();

最终工作

Use:

progressDialog.dismiss();

in end work

热风软妹 2024-11-25 20:34:45

泄漏可能来自您的 PixelRainActivity.staticThis 属性。如果您保留对某个活动的引用,即使该活动已被销毁,也会发生内存泄漏。

最简单的修复方法是使用应用程序的Context。将方法 onCreate() 中的 staticThis = this 行更改为 staticThis = this.getApplicationContext() 并且它应该可以工作(并更改类型staticThisContext(如果情况还不是这样)

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 your staticThis = this line in the method onCreate() to staticThis = this.getApplicationContext() and it should work (and change the type of staticThis to Context if this is not already the case)

老子叫无熙 2024-11-25 20:34:45

在某些情况下,您必须在 onDetachonDestroy 中验证进度对话框是否仍然可见。
就像这样:

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

There are situations when you have to verify in onDetach or in onDestroy if the progress dialog is still visible.
Like so:

@Override
public void onDetach() {
    if (mProgressDialog != null && mProgressDialog.isShowing())
        mProgressDialog.dismiss();
    super.onDetach();
}
温柔一刀 2024-11-25 20:34:45

cygnus 有一个使用 showDialog(MY_INT) 的好主意,其中 MY_INT 只是您选择的一些常量值,只是为了将其与您以这种方式启动的任何其他类似对话框区分开来。您可以使用解雇对话框(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);
}

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:

@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);
}
风为裳 2024-11-25 20:34:45

不要使用 ProgressDialog.show(),而是尝试使用

Activity.showDialog(),它会自动为您管理 Dialog 并防止泄漏。

编辑:当您调用 showDialog(int) 时,它将触发 Activity.onCreateDialog(int) ,您可以在其中创建您想要的 Dialog 并返回您想要显示的Dialog

Instead of using ProgressDialog.show(), try using

Activity.showDialog() which should automatically manage the Dialog for you and prevent leaks.

EDIT: When you call showDialog(int), it will trigger Activity.onCreateDialog(int) where you can create the Dialog you want and return the Dialog you want to display.

故事未完 2024-11-25 20:34:45

我在进度对话框和后台任务中遇到了类似的问题。 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.

凑诗 2024-11-25 20:34:45

最好使用 AsyncTask 在后台从互联网获取某些内容。不过,不需要传递静态上下文。和

new YourAsyncTask(context).execute();

上面的 Activity 一样调用 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;
  }
}

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 activity

new YourAsyncTask(context).execute();

Call AsyncTask like above

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;
  }
}
放我走吧 2024-11-25 20:34:45

如果您正在使用任何 threadAsyncTask 并从互联网下载内容并显示 进度条 ,您应该使用 DialogFragment或者当Activity停止时取消进度dialog,如果您在Asynctask中显示进度,首先取消Asynctask并覆盖< code>oncancel 回调方法和那里关闭进度对话框。

Activityfragment 中的 Window Leak 实际上是由于您尝试添加一个窗口而发生的,而当它显示时,它位于 >foreground,但是当您按下 home 时,它​​会暂停,然后通过 onStop() 停止。因此,您的 CustomView 仍然附加到现在已经消失的窗口。因此,根据系统,您的 customView 占用了它没有释放的空间。

If you are using any thread or AsyncTask and downloading stuff from internet and showing progress bar , you should use DialogFragment or cancel progress dialog when Activity get stop also if you are showing progress in Asynctask fist cancel Asynctask and override oncancel callback method and dismiss progress dialogue there.

Window leak in Activity or fragment is actually occurs due to you are trying to add a window and while it shows up it is on the foreground,but when you are pressing the home it gets paused and then gets stopped via the onStop(). So your CustomView remains attached to the window that now has disappeared.Hence according to the system your customView occupied the space which it did not release.

若相惜即相离 2024-11-25 20:34:45

当另一个 Activity 进入前台时,只需调用 cancel() 方法即可。

@Override
protected void onStop() {
   super.onStop();
   this.mProgress.cancel();
}

Just call the cancel() method when another activity comes into the foreground.

@Override
protected void onStop() {
   super.onStop();
   this.mProgress.cancel();
}
墟烟 2024-11-25 20:34:45

我遇到了这个异常

@Override
    protected void onResume() {
        super.onResume();//at this line
        showProgressDialog();
    }

这个修复对我有用:

  @Override
        protected void onResume() {
            showProgressDialog();
            super.onResume();
        }

I was gettin this exception

@Override
    protected void onResume() {
        super.onResume();//at this line
        showProgressDialog();
    }

This fix worked for me:

  @Override
        protected void onResume() {
            showProgressDialog();
            super.onResume();
        }
心碎无痕… 2024-11-25 20:34:45

尝试在 Activity 被终止之前调用 progressDialog.dismiss() 。我的就这样修好了

Try calling progressDialog.dismiss() before the activity gets killed. I got mine fixed like this.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文