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

Pen*_*m10 1117 android memory-leaks dialog

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

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)
Run Code Online (Sandbox Code Playgroud)

Ale*_*voy 1484

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

[编辑]

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

答案1:

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

答案2

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

答案3

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

  • 即使在8年后,这仍然是相关的!我得到了异常,因为活动在尝试显示我的AlertDialog时被关闭(所以答案2).最后我发现应用程序正在向场景中添加一个"null"对象(不应该发生但它确实发生了)但它没有给它一个额外的例外,整个事情被"泄露"掩盖了窗口"例外. (12认同)
  • 答案3效果很好.解雇() (7认同)
  • 答案3是最好的解决方案。对我很有帮助。谢谢卡泽,亚历克斯!! (3认同)
  • @Override public void onStop(){if(dialog!= null){dialog.dismiss(); dialog = null; }} (2认同)

mol*_*arm 391

解决的办法是打电话给dismiss()Dialog您创建viewP.java:183退出之前Activity,例如onPause().所有的Windows&Dialogs应该在离开之前关闭Activity.

  • 因此,当用户旋转手机时,应取消所有对话框?听起来不对。 (2认同)

ggo*_*eze 107

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

  • 有时在这种情况下,我无法看到真正的异常.要找到真正的异常,只需注释progressDialog.show()并再次运行应用程序..现在你看到它了. (21认同)

Mar*_*lip 66

我被误调用触发此错误的hide(),而不是dismiss()AlertDialog.

  • 究竟是怎么回事我.此外,调用hide()然后将对话框设置为null也不是有效的替代方法. (4认同)

Adr*_*lli 59

你可以通过一个简单/愚蠢的错误来获得这个异常,例如,如果你在switch语句中错过了一个break调用语句,那么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;
        }
    }
Run Code Online (Sandbox Code Playgroud)

finish()方法将关闭Activity,但AlertDialog仍然显示!

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


Sho*_*med 35

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

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

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

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


Ruc*_*nia 33

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

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

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

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

所以,看看你的逻辑.解决第一个错误,然后第二个错误将自行解决在此输入图像描述

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

  • 不能相信这只有一次投票..或者我们真的在编程方面很不好哈哈哈我也喜欢你的多米诺骨牌 (2认同)
  • 这并不完全正确,手机旋转等情况也可能导致“活动”旋转发生。 (2认同)

Tus*_*har 19

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

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

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


san*_*ndy 14

这可能有所帮助.

if (! isFinishing()) {

    dialog.show();

    }
Run Code Online (Sandbox Code Playgroud)

  • 在数百个类似的答案中,没有人展示如何检查窗口是否存在.所以你节省了一些时间来找到方法.谢谢. (2认同)

Muh*_*Ali 14

活动销毁时关闭对话框

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


Mel*_*een 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();
}
Run Code Online (Sandbox Code Playgroud)

覆盖OnPausewith调用mVideoView.pause()和设置visibilityGONE.这样我就可以解决" Activity has leaked window"日志错误问题.


Kit*_*mos 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();
}
Run Code Online (Sandbox Code Playgroud)

如果你在我在那里调完完之后没有把它放回去,那就好像你已经在它之后调用它一样alert.show();,因此它会说你在对话框出现之后就完成了窗口的泄漏,即使这是不是这样,它仍然认为是.

我想我会在这里添加这个,因为这显示了完成命令的行为不同然后我认为它做了,我猜有其他人在我发现这个之前的想法和我做的一样.


Kil*_*ler 7

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

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

 android:noHistory="true"
Run Code Online (Sandbox Code Playgroud)

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


dmz*_*mz9 7

当您确实想关闭AlertDialog 但不想在活动中保留对它的引用时,这是一个解决方案。

解决方案要求您在项目中具有androidx.lifecycle依赖项(我相信在评论时这是一个常见要求)

这使您可以将对话框的解除委托给外部对象(观察者),并且您不再需要关心它,因为它会在活动结束时自动取消订阅。(这里有证据:https : //github.com/googlecodelabs/android-lifecycles/issues/5)。

因此,观察者保持对对话的引用,而活动保持对观察者的引用。当“onPause”发生时 - 观察者关闭对话框,当“onDestroy”发生时 - 活动移除观察者,所以不会发生泄漏(好吧,至少我不再在 logcat 中看到错误)

// observer
class DialogDismissLifecycleObserver( private var dialog: AlertDialog? ) : LifecycleObserver {
    @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
    fun onPause() {
        dialog?.dismiss()
        dialog = null
    }
}
// activity code
private fun showDialog() {
        if( isDestroyed || isFinishing ) return
        val dialog = AlertDialog
            .Builder(this, R.style.DialogTheme)
            // dialog setup skipped
            .create()
        lifecycle.addObserver( DialogDismissLifecycleObserver( dialog ) )
        dialog.show()
}

Run Code Online (Sandbox Code Playgroud)


Kul*_*kar 6

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

例:

OldActivity instance;

    oncreate() {
       instance=this;
    }
    instance.finish();
    instance.startActivity(new Intent(ACTION_MAIN).setClass(instance, NewActivity.class));
Run Code Online (Sandbox Code Playgroud)


Kyl*_*egg 5

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

你有两个选择AFAIK:

  1. 重新考虑你的警报的登录:调用dismiss()dialog实际退出你的活动之前.
  2. 将其dialog置于不同的线程并在其上运行thread(独立于当前activity).


Leo*_*onS 5

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

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


tin*_*nku 5

试试这段代码:

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

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

}
Run Code Online (Sandbox Code Playgroud)


Nic*_*hek 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();
Run Code Online (Sandbox Code Playgroud)


SAN*_*NAT 5

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

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

progressDialog.dismiss(); // Use it
Run Code Online (Sandbox Code Playgroud)


Bap*_*nde 5

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

 // 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();
                }
            }
Run Code Online (Sandbox Code Playgroud)


Har*_*ali 5

它可能对访问此问题的人有所帮助。

show()您应该在对话之前检查活动和对话的安全状况dismiss()

在显示对话框之前添加以下条件

    if (!isFinishing && !isDestroyed && !dialog.isShowing) {
         dialog.show()
    }
Run Code Online (Sandbox Code Playgroud)

在关闭对话框之前添加以下条件

    if (!isFinishing && !isDestroyed && dialog.isShowing) {
         dialog.dismiss()
    }
Run Code Online (Sandbox Code Playgroud)
  • isFinishing并将isDestroyed保证活动(从何处Dialog发起)不处于 isFinishingisDestroyed状态。有时,当对话框托管活动即将破坏并且我们面临“泄漏窗口”问题时,我们会尝试打开对话框

  • dialog.isShowing检查对话框之前的show()对话框状态dismiss()