代码之家  ›  专栏  ›  技术社区  ›  Pentium10

活动泄漏了最初添加的窗口

  •  1032
  • Pentium10  · 技术社区  · 15 年前

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

    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)
    
    38 回复  |  直到 6 年前
        1
  •  1381
  •   Kaze Notus    8 年前

    退出活动后,您试图显示一个对话框。

    [编辑]

    这个问题是谷歌搜索Android开发者的首选之一, 因此,从评论中添加一些重要的观点,这可能对未来的研究者更有帮助,而无需深入讨论评论。

    答案1 :

    退出活动后,您试图显示一个对话框。

    答案2

    在某些情况下,这个错误可能有点误导(尽管 答案仍然是完全准确的),即在我的案例中, 在AsyncTask中引发了未处理的异常,这导致 活动关闭,然后打开的ProgressDialog导致 例外…所以“真正的”例外在日志中有点早。

    答案3

    在退出您的 活动,例如在OnPause()或OnDestroy()中

        2
  •  382
  •   Catalina    10 年前

    解决办法是打电话 dismiss() Dialog 你创造了 viewP.java:183 在退出之前 Activity ,例如 onPause() . 所有 Window 标准普尔; 对话 在离开 活动 .

        3
  •  105
  •   bofredo    12 年前

    如果您正在使用 AsyncTask ,可能日志消息具有欺骗性。如果在日志中查找,可能会发现另一个错误,可能是 doInBackground() 你的方法 异步任务 ,那是你的电流 Activity 爆炸,因此一旦 异步任务 回来…好吧,其余的你都知道。其他一些用户已经在这里解释了这一点:—)

        4
  •  55
  •   Mark Phillip    12 年前

    我打错了电话,引起了这个错误 hide() 而不是 dismiss() 关于一个 AlertDialog .

        5
  •  53
  •   Catalina    10 年前

    您可以通过一个简单/愚蠢的错误(例如)意外地调用 finish() 在展示了 AlertDialog ,如果在switch语句中缺少break call语句…

       @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;
            }
        }
    

    这个 FIX() 方法将关闭 Activity 但是 对话框 仍在显示!

    因此,当您专注于代码、寻找糟糕的线程问题或复杂的编码等等时,不要忽视树的森林。有时候,它可能只是一个简单而愚蠢的东西,就像一个缺失的break语句。:)

        6
  •  30
  •   Stephan    13 年前

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

    我只是通过写下以下代码来解决这个问题:

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

    基本上,从哪个类开始ProgressDialog,重写OnDestroy方法,然后这样做。它解决了“活动漏窗”的问题。

        7
  •  24
  •   Ruchir Baronia    8 年前

    这个问题的答案都是正确的,但让我有点困惑,无法真正理解为什么。在玩了大约2个小时之后,这个错误的原因(在我的例子中)击中了我:

    通过阅读其他答案,您已经知道has x has leaked window decorview@d9e6131[] error means a dialog was open when your app closed.但是为什么呢?

    可能是,当您的对话框打开时,您的应用程序由于其他原因崩溃了

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

    那么,看看你的逻辑。解决第一个错误,然后第二个错误将自行解决 . >.

    一个错误会导致另一个错误,这会导致另一个错误,比如多米诺骨牌!

    这一错误的原因(在我的情况下)击中了我:

    你已经从阅读其他答案中知道 X has leaked window DecorView@d9e6131[] 错误表示应用程序关闭时打开了一个对话框。但是为什么呢?

    可能是,当你的对话打开时,你的应用因为其他原因崩溃了。

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

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

    一个错误会导致另一个错误,就像多米诺骨牌一样!

        8
  •  19
  •   Tushar    13 年前

    我最近也面临同样的问题。

    此问题背后的原因是,在取消对话框之前正在关闭活动。 上述情况发生的原因多种多样。以上各帖所述也正确。

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

        9
  •  12
  •   sandy    12 年前

    这可能会有所帮助。

    if (! isFinishing()) {
    
        dialog.show();
    
        }
    
        10
  •  12
  •   Muhammad Aamir Ali    12 年前

    活动破坏时关闭对话框

    @Override
    protected void onDestroy()
    {
        super.onDestroy();
        if (pDialog!=null && pDialog.isShowing()){
            pDialog.dismiss();
        }
    }
    
        11
  •  11
  •   Melinda Green    14 年前

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

        12
  •  11
  •   rafsanahmad007    8 年前

    我正在我的视频播放器应用程序中获取这些日志。这些消息是在视频播放器关闭时抛出的。有趣的是,我曾经以随机方式每隔几次获取这些日志。我的申请也不涉及 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 “日志错误问题。

        13
  •  10
  •   Rohit Sharma Bigyelow    7 年前

    我有同样的问题,找到了这个页面,当我的情况不同时,我打电话给 finish 从A if 在它定义警报框之前阻止。

    所以,只要打电话 dismiss 不会工作(因为它还没有被制作出来),但在阅读之后 Alex Volovoy 回答并意识到是警报箱引起的。我试图在里面完成后添加一个返回语句 如果 布洛克解决了这个问题。

    我想,一旦你调用finish,它就停止了所有的工作,并在那里完成了所有的工作,但它没有完成。它似乎走到了代码块的末尾,然后结束了。

    所以,如果你想实现这样一种情况,有时它会在代码执行之前完成,你必须在完成之后放一个RETURN语句,否则它会继续执行,并且表现得像在代码块末尾调用finish,而不是在你调用它的地方。这就是为什么我会犯那些奇怪的错误。

    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(); 因此,它会说窗口是在你让对话框出现后才完成的,即使不是这样,它仍然认为是这样。

    我想我会在这里加上这个,因为这表明finish命令的行为与我想的不同,我猜还有其他人和我发现这个之前一样。

        14
  •  7
  •   Shubham AgaRwal    9 年前

    这不是问题的答案,但与主题有关。

    如果活动在清单中定义了属性

     android:noHistory="true"
    

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

        15
  •  6
  •   glennsl Namudon'tdie    7 年前

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

    例子:

    OldActivity instance;
    
        oncreate() {
           instance=this;
        }
        instance.finish();
        instance.startActivity(new Intent(ACTION_MAIN).setClass(instance, NewActivity.class));
    
        16
  •  5
  •   LeonS    12 年前

    有一个问题,当ProgressDialog仍然显示时,我完成了一个活动。

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

        17
  •  5
  •   nickhar    12 年前

    试试这个代码:

    public class Sample extends Activity(){
    @Override
     public void onCreate(Bundle instance){
    
    }
     @Override
        public void onStop() {
            super.onStop();
          progressdialog.dismiss(); // try this
        }
    
    }
    
        18
  •  5
  •   Tushar Gupta - curioustushar    12 年前

    如果您在 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();
    
        19
  •  5
  •   SANAT    9 年前

    当我使用 ProgressDialog 在里面 AsyncTask . 实际上我在用 hide() 方法在 onPostExecute . 根据@alex volovoy的回答,我需要使用 dismiss() 具有 进度对话框 在OnPostExecute中删除它并完成它。

    progressDialog.hide(); // Don't use it, it gives error
    
    progressDialog.dismiss(); // Use it
    
        20
  •  5
  •   rafsanahmad007    8 年前

    Activity has leaked window that was originally added... “当您尝试在 Activity 有效地 finished .

    您有两个选择Afaik:

    1. 重新考虑警报的登录:调用 dismiss() dialog 在实际退出活动之前。
    2. 对话 在另一个线程中运行它 thread (与电流无关 activity )
        21
  •  4
  •   rafsanahmad007    8 年前

    你必须做 Progressdialog 对象在 onPreExecute 方法 AsyncTask 你应该 dismiss 它在 onPostExecute 方法。

        22
  •  4
  •   Bapusaheb Shinde    7 年前

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

     // 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
  •  3
  •   Matthew Quiros    13 年前

    在我的案例中,原因是我忘记在Android清单文件中包含权限。

    我怎么知道的?好吧,就像@bobby在接受答案下面的评论中所说的那样,只要向上滚动到日志,您就会看到第一个真正引发异常的原因或事件。显然,消息“activity has leaked window that was original added”只是由第一个异常所导致的异常。

        24
  •  3
  •   Ness Tyagi    7 年前

    最好的解决方案是在发生异常时在Try-Catch和Disclose对话框中添加对话框。

    使用下面的代码

     try {
            dialog.show();
        } catch (Exception e) {
            dialog.dismiss();
        }
    
        25
  •  2
  •   Developer    11 年前

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

    try {
            if (null != progressDialog && progressDialog.isShowing()) {
                progressDialog.dismiss();
                progressDialog = null;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    
        26
  •  2
  •   Sherry    10 年前

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

    1)当活动上下文不存在时显示对话框,要解决此问题,应仅显示对话框,确保活动存在:

    if(getActivity()!= null && !getActivity().isFinishing()){
            Dialog.show();
    }
    

    2)不要适当地关闭对话框,以解决使用此代码的问题:

    @Override
    public void onDestroy(){
        super.onDestroy();
        if ( Dialog!=null && Dialog.isShowing() ){
            Dialog.dismiss();
    }
    }
    
        27
  •  2
  •   Ali Akram    7 年前

    最好的解决办法是在展示前先放这个 progressbar progressDialog

    if (getApplicationContext().getWindow().getDecorView().isShown()) {
    
      //Show Your Progress Dialog
    
    }
    
        28
  •  1
  •   Manas Ranjan    11 年前

    只需确保您的活动不会因代码中的某些异常而意外关闭。通常在异步任务中,当活动在doinbackground方法中面临强制关闭,然后AsyncTask返回到onPostExecute方法时,会发生这种情况。

        29
  •  1
  •   androidmalin    9 年前
      if (mActivity != null && !mActivity.isFinishing() && mProgressDialog != null && mProgressDialog.isShowing()) {
            mProgressDialog.dismiss();
        }
    
        30
  •  1
  •   Satish Silveri    8 年前

    根据我的说法,问题是你在一个活动完成后就试图调用一个对话框,所以根据我的说法,你可以做的是使用处理程序延迟一些时间,这样你的问题就会得到解决,例如:

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