活动已泄露最初添加的窗口

问题描述 投票:1056回答:39

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

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)
android memory-leaks dialog
39个回答
1442
投票

您在退出活动后尝试显示对话框。

[编辑]

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

答案1:

您在退出活动后尝试显示对话框。

答案2

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

答案3

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


13
投票

活动销毁时关闭对话框

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

11
投票

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


11
投票

我在我的视频播放器应用程序中获取这些日志。视频播放器关闭时抛出这些消息。有趣的是,我曾经以随机方式在几次运行中获取这些日志。我的申请也不涉及任何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();
}

通过调用OnPause和将mVideoView.pause()设置为visibility来覆盖GONE。这样我就可以解决“Activity has leaked window”日志错误问题。


10
投票

我遇到了同样的问题并找到了这个页面,虽然我的情况不同,但在定义警报框之前,我从finish块调用了if

所以,简单地调用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();之后调用了它,因此它会说你在对话框出现之后就完成了窗口的泄漏,即使事实并非如此,它仍然认为是这样的。

我想我会在这里添加这个,因为这显示了完成命令的行为不同然后我认为它确实如此,我猜有其他人在我发现这个之前就像我一样。


7
投票

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

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

 android:noHistory="true"

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


6
投票

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

例:

OldActivity instance;

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

5
投票

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

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


5
投票

试试这段代码:

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

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

}

5
投票

这可能是因为你在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();

5
投票

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

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

progressDialog.dismiss(); // Use it

387
投票

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


5
投票

Activity has leaked window that was originally added...实际上是Activity后尝试显示警报时,会出现“finished”错误。

你有两个选择AFAIK:

  1. 重新思考警报的登录:在实际退出活动之前,在dismiss()上调用dialog
  2. dialog放在另一个线程中并在thread上运行(独立于当前的activity)。

4
投票

你必须在ProgressdialogonPreExecute方法中制作AsyncTask对象,你应该在dismiss方法上使用onPostExecute


4
投票

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

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

3
投票

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

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


3
投票

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

只需使用下面的代码

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

2
投票

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

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

2
投票

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

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

2
投票

在展示progressbarprogressDialog之前,最好的解决方案是这个

if (getApplicationContext().getWindow().getDecorView().isShown()) {

  //Show Your Progress Dialog

}

1
投票

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


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

106
投票

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


1
投票

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

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

                }
            },100);

61
投票

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


54
投票

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

   @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仍然显示!

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


31
投票

在退出活动后尝试显示对话框时出现此问题。

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

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

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


29
投票

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

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

可能是,当您的对话框打开时,您的应用程序因某些其他原因而崩溃

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

所以,看看你的逻辑。解决第一个错误,然后第二个错误将解决自己enter image description here

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


19
投票

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

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

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


13
投票

这可能有所帮助。

if (! isFinishing()) {

    dialog.show();

    }
© www.soinside.com 2019 - 2024. All rights reserved.