提问



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


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)

最佳参考


在退出Activity后,您将尝试显示一个Dialog。


[[编辑]]


这个问题是google for android开发者的热门搜索之一,
因此,从评论中添加一些重要的观点,这可能对未来的调查员更有帮助,而无需进行深入的评论对话。


回答1 :



  在退出Activity后,您将尝试显示一个Dialog。



回答2



  在某些情况下,这个错误可能会有点误导(尽管如此)
  答案仍然是完全准确的) - 即在我的情况下
  未处理的异常被抛入AsyncTask,导致了
  要关闭的Activity,然后打开progressdialog导致这个
  例外..所以真正的例外在日志中稍早一点



回答3



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


其它参考1


解决方法是在退出Activity之前,在viewP.java:183中创建的Dialog上调用dismiss(),例如在onPause()中。所有Window s& Dialog s应在离开Activity之前关闭。

其它参考2


如果您使用AsyncTask,那么该日志消息可能具有欺骗性。如果你在日志中查找,你可能会发现另一个错误,可能是你AsyncTask doInBackground()方法中的一个错误,就是让你当前Activity爆炸,因此一旦AsyncTask回来..好吧,你知道其余的。其他一些用户已在此处解释:-)

其它参考3


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


   @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()方法将关闭Activity,但AlertDialog仍然显示!


因此,当你专心盯着代码,寻找糟糕的线程问题或复杂的编码等等时,不要忽视树林的森林。有时它可能只是一个简单而愚蠢的东西,就像一个缺失的断言。 :)

其它参考4


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

其它参考5


在您退出Activity后尝试显示对话框时会出现此问题。


我刚刚通过写下以下代码解决了这个问题:


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


基本上,从哪个类开始progressDialog,覆盖onDestroy方法并以这种方式执行。它解决了Activity已泄露窗口的问题。

其它参考6


我最近遇到了同样的问题。


这个问题背后的原因是在关闭对话框之前关闭了Activity。
上述情况有多种原因发生。上面帖子中提到的那些也是正确的。


我遇到了一个情况,因为在线程中,我正在调用一个抛出异常的函数。因为窗户被解雇,因此例外。

其它参考7


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


通过阅读其他答案,您已经知道X has leaked window DecorView@d9e6131[]错误意味着当您的应用关闭时对话框已打开。但为什么?


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


这导致您的应用关闭,因为您的代码中存在一些错误,导致对话框因应用程序因其他错误而关闭的同时保持打开状态。


所以,看看你的逻辑。解决第一个错误,然后第二个错误将自行解决 [80]


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

其它参考8


我有同样晦涩的错误信息,不知道为什么。根据之前答案的线索,我将我的非GUI调用mDialog.finish()更改为mDialog.dismiss(),错误消失了。这并没有影响我的小部件的行为,但它令人不安,很可能已经标记了一个重要的内存泄漏。

其它参考9


我在我的视频播放器应用程序中获取这些日志。视频播放器关闭时抛出这些消息。有趣的是,我曾经以随机方式在几次运行中获取这些日志。我的申请也不涉及任何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()覆盖OnPause并将visibility设置为GONE。这样我就可以解决Activity has leaked window日志错误问题。

其它参考10


Activity销毁时关闭对话框


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

其它参考11


我遇到了同样的问题并找到了这个页面,虽然我的情况不同,但我在if块中调用了finish,然后才定义了警告框。


因此,简单地调用dismiss将不起作用(因为它尚未制作)但是在阅读 Alex Volovoy的答案并意识到它是引起它的警报框之后。我试过了在if块内完成后立即添加一个return语句并修复了问题。


我想,一旦你打电话给它完成它就停止了一切并完成了那里,但它没有。它似乎已经完成了代码块的结尾。


所以,如果你想要实现一种情况,有时它会在完成一些代码之前完成,你必须在完成之后立即放置一个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();之后调用了它,因此它会说你在完成对话后完成了窗口的泄漏虽然事实并非如此,但它仍然认为是这样。


我想我会在这里添加这个,因为这表明结束命令采取了不同的行动,然后我认为它确实如此,我猜我还有其他人在我发现这个之前就像我一样。

其它参考12


这可能有所帮助。


if (! isFinishing()) {

    dialog.show();

    }

其它参考13


这不是问题的答案,但它与该主题相关。


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


 android:noHistory="true"


然后在执行onPause()之后,Activity的上下文就会丢失。因此,使用此上下文的所有视图都可能会出现此错误。

其它参考14


不仅尝试显示警报,还可以在完成特定Activity实例并尝试启动新Activity/服务或尝试停止时调用它。


示例:


OldActivity instance;

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

其它参考15


如果您在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();

其它参考16


当我在AsyncTask中使用ProgressDialog时,这发生在我身上。实际上我在onPostExecute中使用hide()方法。基于@Alex Volovoy的答案,我需要使用dismiss()ProgressDialog在onPostExecute中删除它并完成它。


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

progressDialog.dismiss(); // Use it

其它参考17


Activity有效finished后尝试显示警报时,会出现Activity has leaked window that was originally added...错误。


你有两个选择AFAIK:



  1. 重新考虑提醒您:在实际退出Activity之前,请dialog调用dismiss()

  2. dialog放在另一个线程中并在thread上运行(与当前activity无关。)


其它参考18


如果仍然显示ProgressDialog,我在完成Activity的问题。


首先隐藏对话框,然后完成Activity。

其它参考19


试试这段代码:


public class Sample extends Activity(){
@Override
 public void onCreate(Bundle instance){

}
 @Override
    public void onStop() {
        super.onStop();
      progressdialog.dismiss(); // try this
    }

}

其它参考20


你必须在AsyncTaskAsyncTask方法中设置Progressdialog对象,你应该在onPostExecute方法上dismiss

其它参考21


最佳解决方案是在发生异常时在try catch和dismiss对话框中添加对话框



  只需使用下面的代码



 try {
        dialog.show();
    } catch (Exception e) {
        dialog.dismiss();
    }

其它参考22


通常由于进度对话框而发生此问题:您可以通过在Activity中使用以下任一方法来解决此问题:


 // 1):
          @Override
                protected void onPause() {
                    super.onPause();
                    if ( yourProgressDialog!=null && yourProgressDialog.isShowing() )
                  {
                        yourProgressDialog.cancel();
                    }
                }

       // 2) :
         @Override
            protected void onDestroy() {
                super.onDestroy();
                if ( yourProgressDialog!=null && yourProgressDialog.isShowing()
               {
                    yourProgressDialog.cancel();
                }
            }

其它参考23


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


我是怎么知道的?好吧,就像@Bobby在接受的答案下面的评论中说的那样,只需向上滚动到你的日志,你就会看到真正引发异常的第一个原因或事件。显然,消息Activity已经泄露了原来的窗口添加只是一个异常,是由第一个异常引起的。

其它参考24


尝试下面的代码,它将在您解除进度对话框的任何时候工作,它将查看其实例是否可用。


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

其它参考25


由于代码中某处出现了一些异常,请确保您的Activity未意外关闭。通常,当Activity面临强制关闭doinBackground方法然后asynctask返回onPostexecute方法时,它发生在异步任务中。

其它参考26


窗口泄露异常有两个原因:


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();
}
}

其它参考27


  if (mActivity != null && !mActivity.isFinishing() && mProgressDialog != null && mProgressDialog.isShowing()) {
        mProgressDialog.dismiss();
    }

其它参考28


根据我的问题是你试图在一个Activity完成后立即调用一个对话框,所以根据我你可以做的是使用Handler给你一些延迟,你的问题将被解决,例如:


 Handler handler=new Handler();
     handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                     dialog.show();
                     //or
                     dialog.dismiss();

                }
            },100);

其它参考29


我有同样的问题。错误不在Dialog中,而在EditText中。我试图改变AssynctaskEdittext的值。我唯一能解决的就是创造一个新的runnable


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