Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/218.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android ProgressDialog:如何防止窗口泄漏_Android_Memory Leaks_Progressdialog - Fatal编程技术网

Android ProgressDialog:如何防止窗口泄漏

Android ProgressDialog:如何防止窗口泄漏,android,memory-leaks,progressdialog,Android,Memory Leaks,Progressdialog,我使用ProgressDialog阻止用户在设备从internet下载内容时进行交互 在我的客户设法产生此错误之前,一切都正常: "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

我使用ProgressDialog阻止用户在设备从internet下载内容时进行交互

在我的客户设法产生此错误之前,一切都正常:

"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)"
如果我把它改成这样,它能解决问题吗

this.runOnUiThread(new Runnable() {
            public void run() {
                progressDialog = ProgressDialog.show(PixelRainActivity.staticThis, "",PixelRainActivity.staticThis.getResources().getString( R.string.draftProgressMessage), true);
            }
        });

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

Activity.showDialog()
它将自动为您管理
对话框
,并防止泄漏


编辑:当你调用
showDialog(int)
时,它将触发
活动。onCreateDialog(int)
在那里你可以创建你想要的
对话框并返回你想要显示的
对话框。

我在进度对话框和后台任务中遇到了类似的问题。AsyncTask()使我可以更干净地完成这两项工作,而不必使用泄漏的窗口。

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


最简单的修复方法是使用应用程序的
上下文。将方法
onCreate()
中的
staticThis=this
行更改为
staticThis=this.getApplicationContext()
,它应该可以工作(如果不是这样的话,将
staticThis
的类型更改为
Context

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


在结束工作时

如果您正在使用任何
线程
异步任务
并从internet下载内容并显示
进度条
,如果在
异步任务
中显示进度,则在
活动
停止时也应使用
对话框片段
或取消进度
对话框
,并覆盖
oncancel
回调方法和
取消
进度对话框


活动
片段
中的
窗口泄漏
实际上是由于您试图添加一个窗口而发生的,当它显示在
前台时
,但当您按下home键时,它会暂停,然后通过顶部的
停止。因此,您的
CustomView
仍然连接到现在已消失的窗口。因此,根据系统,您的
CustomView
占用了它未释放的空间。

最好使用
AsyncTask
在后台从internet获取内容。但是,不需要传递静态上下文。和活动

new YourAsyncTask(context).execute();
像上面那样调用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;
  }
}
私有类YourAsynTask扩展了异步任务
{
私人语境;
私有进程对话;
//在构造函数中传递上下文
公共YourAsynTask(上下文)
{
this.context=上下文;
}
//显示onPre的进展
@凌驾
受保护的void onPreExecute()
{
//在这里显示进度代码。
progressDialog=progressDialog.show(上下文“,”正在加载。请稍候…,true);
}
//关闭onPost中的“进度”对话框
@凌驾
受保护的void OnPostExecute(字符串响应)
{
如果(progressDialog!=null)
progressDialog.disclose();
progressDialog=null;
}
}

在某些情况下,如果进度对话框仍然可见,则必须在
onDetach
onDestroy
中进行验证。 像这样:


在活动终止之前,尝试调用
progressDialog.dismise()
。我的问题是这样解决的。

当另一个活动进入前台时,只需调用cancel()方法

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

我遇到了这个例外

@Override
    protected void onResume() {
        super.onResume();//at this line
        showProgressDialog();
    }
此修复对我有效:

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

我也遇到了同样的问题,只有在活动暂停时打开
对话框时才会出现。是这样吗?或者可能是在更改方向时?请更新已接受的答案,使其使用
discover
但不使用Activity.showDialog()我需要将a ID传递给对话框,然后如何显示进度对话框?对我来说不起作用。我正在异步任务的onPreExecute()中使用progressDialog.show()。我得到:android.view.WindowManager$BadTokenException:无法添加窗口--标记null不适用于应用程序为了创建对话框,您必须传递的不是上下文,而是活动。因此,此.getApplicationContext()不正确根据此,在这种情况下使用getApplicationContext将抛出一个错误:-1@Guillaume Brunerie-您必须将活动实例作为上下文传递,因为该操作是在UI中执行的。因此传递getApplicationContext()将导致异常。该链接是一个死端。我错误地调用了hide而不是disclose()。谢谢。要添加答案:您可能应该在
onDestroy()
中调用
progressDialog.dismise()
(但在调用
super.onDestroy()
)之前,最好通过
活动检查活动是否处于活动状态!=空&!activity.isFinishing()
在显示进度对话框之前
@Override
protected void onStop() {
   super.onStop();
   this.mProgress.cancel();
}
@Override
    protected void onResume() {
        super.onResume();//at this line
        showProgressDialog();
    }
  @Override
        protected void onResume() {
            showProgressDialog();
            super.onResume();
        }