android 活动已泄露窗口 com.android.internal.policy.impl.phonewindow$decorview 问题

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12000940/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 09:25:17  来源:igfitidea点击:

android activity has leaked window com.android.internal.policy.impl.phonewindow$decorview Issue

androidandroid-layoutmemory-leaksandroid-alertdialog

提问by Ponmalar

I am working with Android application to show network error.

我正在使用 Android 应用程序来显示网络错误。

NetErrorPage.java

网络错误页面

package exp.app;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class NetErrorPage extends Activity implements OnClickListener {    

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.neterrorlayout);
        Button reload=(Button)findViewById(R.id.btnReload);
        reload.setOnClickListener(this);    
        showInfoMessageDialog("Please check your network connection","Network Alert"); 
    }

    public void onClick(View arg0)             
        {
            if(isNetworkAvailable())
            {                   
                Intent myIntent = new Intent((Activity)NetErrorPage.this, MainActivity.class);   
                myIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);              
                ((Activity)NetErrorPage.this).startActivity(myIntent);
                finish();
            }
            else
                showInfoMessageDialog("Please check your network connection","Network Alert");
    }

    public void showInfoMessageDialog(String message,String title)
       {
        AlertDialog alertDialog = new AlertDialog.Builder(NetErrorPage.this).create();
        alertDialog.setTitle("Network Alert");
        alertDialog.setMessage(message);
        alertDialog.setButton("OK",
                new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog,int which) 
                    {   
                        dialog.cancel();
                    }
                });            
        alertDialog.show();
    }

 private boolean isNetworkAvailable()
    {
        NetworkInfo ActiveNetwork;
        @SuppressWarnings("unused")
        String IsNetworkConnected;
        @SuppressWarnings("unused")
        String ConnectionType;
        ConnectivityManager connectivitymanager;
        connectivitymanager=(ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);        
        try
        {           
            ActiveNetwork=connectivitymanager.getActiveNetworkInfo();
            ConnectionType=ActiveNetwork.getTypeName(); 
            IsNetworkConnected=String.valueOf(ActiveNetwork.getState());
            return true;                        
        }
        catch(Exception error)
        {
                return false;
        }
    }    
}

but i'm getting the error as below,

但我收到如下错误,

08-17 11:59:08.019: E/WindowManager(16460): Activity exp.app.NetErrorPage has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@40534a18 that was originally added here
08-17 11:59:08.019: E/WindowManager(16460): android.view.WindowLeaked: Activity exp.app.NetErrorPage has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@40534a18 that was originally added here
08-17 11:59:08.019: E/WindowManager(16460):     at android.view.ViewRoot.<init>(ViewRoot.java:263)
08-17 11:59:08.019: E/WindowManager(16460):     at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:148)
08-17 11:59:08.019: E/WindowManager(16460):     at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:91)
08-17 11:59:08.019: E/WindowManager(16460):     at android.view.Window$LocalWindowManager.addView(Window.java:424)
08-17 11:59:08.019: E/WindowManager(16460):     at android.app.Dialog.show(Dialog.java:241)
08-17 11:59:08.019: E/WindowManager(16460):     at sync.directtrac.NetError.showInfoMessageDialog(NetErrorPage.java:114)
08-17 11:59:08.019: E/WindowManager(16460):     at sync.directtrac.NetError.onCreate(NetErrorPage.java:26)
08-17 11:59:08.019: E/WindowManager(16460):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
08-17 11:59:08.019: E/WindowManager(16460):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1615)
08-17 11:59:08.019: E/WindowManager(16460):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1667)
08-17 11:59:08.019: E/WindowManager(16460):     at android.app.ActivityThread.access00(ActivityThread.java:117)
08-17 11:59:08.019: E/WindowManager(16460):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:935)
08-17 11:59:08.019: E/WindowManager(16460):     at android.os.Handler.dispatchMessage(Handler.java:99)
08-17 11:59:08.019: E/WindowManager(16460):     at android.os.Looper.loop(Looper.java:130)
08-17 11:59:08.019: E/WindowManager(16460):     at android.app.ActivityThread.main(ActivityThread.java:3687)
08-17 11:59:08.019: E/WindowManager(16460):     at java.lang.reflect.Method.invokeNative(Native Method)
08-17 11:59:08.019: E/WindowManager(16460):     at java.lang.reflect.Method.invoke(Method.java:507)
08-17 11:59:08.019: E/WindowManager(16460):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867)
08-17 11:59:08.019: E/WindowManager(16460):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:625)
08-17 11:59:08.019: E/WindowManager(16460):     at dalvik.system.NativeStart.main(Native Method)

I have searched more... but i don't have any right idea to clear this.

我已经搜索了更多......但我没有任何正确的想法来清除这个。

What i want is, when loading this page, layout should be added and dialog should be shown.

我想要的是,在加载此页面时,应添加布局并显示对话框。

Please help me to clear this error

请帮我清除这个错误

Note:I have tried this also

注意:我也试过这个

@Override
    protected void onResume() {
    super.onResume();
        runOnUiThread(new Runnable() {
            public void run() {
                showInfoMessageDialog("Please check your network connection","Network Alert");
            }
        });

    }

回答by Ponmalar

Thank you Guys to give me many suggestions. Finally I got a solution. That is i have started the NetErrorPage intent two times. One time, i have checked the net connection availability and started the intent in page started event. second time, if the page has error, then i have started the intent in OnReceivedError event. So the first time dialog is not closed, before that the second dialog is called. So that i got a error.

谢谢你们给我很多建议。最后我得到了一个解决方案。那是我已经启动了两次 NetErrorPage 意图。有一次,我检查了网络连接可用性并在页面启动事件中启动了意图。第二次,如果页面有错误,那么我已经在 OnReceivedError 事件中启动了意图。所以第一次对话框没有关闭,在此之前第二个对话框被调用。所以我得到了一个错误。

Reason for the Error: I have called the showInfoMessageDialog method two times before closing the first one.

错误原因:在关闭第一个方法之前,我已经调用了两次 showInfoMessageDialog 方法。

Now I have removed the second call and Cleared error :-).

现在我已经删除了第二个调用并清除了错误:-)。

回答by Chirag

Change this dialog.cancel();to dialog.dismiss();

将此更改dialog.cancel();dialog.dismiss();

The solution is to call dismiss()on the Dialogyou created in NetErrorPage.java:114before exiting the Activity, e.g. in onPause().

解决的办法是呼叫dismiss()Dialog你中创建NetErrorPage.java:114退出之前Activity,在如onPause()

Views have a reference to their parent Context(taken from constructor argument). If you leave an Activitywithout destroying Dialogs and other dynamically created Views, they still hold this reference to your Activity(if you created with this as Context: like new ProgressDialog(this)), so it cannot be collected by the GC, causing a memory leak.

视图有对其父级的引用Context(取自构造函数参数)。如果你在Activity不销毁Dialogs 和其他动态创建的Views的情况下离开,它们仍然持有对你的这个引用Activity(如果你用 this 作为Context:like创建new ProgressDialog(this)),所以它不能被 GC 收集,导致内存泄漏。

回答by CoolMind

In my case finish()executed immediately after a dialog has shown.

在我的情况下finish(),在显示对话框后立即执行。

回答by Haresh Chaudhary

Please try this Way And Let me know :

请尝试这种方式并让我知道:

Context mContext;
@Override
public void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
   setContentView(R.layout.neterrorlayout);

   mContext=NetErrorPage.this;
   Button reload=(Button)findViewById(R.id.btnReload);
   reload.setOnClickListener(this);    
   showInfoMessageDialog("Please check your network connection","Network Alert"); 
}
public void showInfoMessageDialog(String message,String title)
{
   new AlertDialog.Builder(mContext)
   .setTitle("Network Alert");
   .setMessage(message);
   .setButton("OK",new DialogInterface.OnClickListener() {
       public void onClick(DialogInterface dialog,int which) 
       {   
          dialog.cancel();
       }
   })
   .show();
}

回答by nandeesh

The dialog needs to be started only after the window states of the Activity are initialized This happens only after onresume.

对话框需要在Activity的窗口状态被初始化之后才需要启动。这种情况只有在onresume之后才会发生。

So call

所以打电话

runOnUIthread(new Runnable(){

    showInfoMessageDialog("Please check your network connection","Network Alert");
});

in your OnResume function. Do not create dialogs in OnCreate
Edit:

在您的 OnResume 函数中。不要在 OnCreate Edit 中创建对话框

use this

用这个

Handler h = new Handler();

h.postDelayed(new Runnable(){

        showInfoMessageDialog("Please check your network connection","Network Alert");
    },500);

in your Onresume instead of showonuithread

在你的 Onresume 而不是 showonuithread

回答by Carlos Rojas

 @Override
    protected void onPostExecute(final Boolean success) {
        mProgressDialog.dismiss();
        mProgressDialog = null;

setting the value null works for me

设置值 null 对我有用

回答by David Onyango

The way I got around this issue is by not calling intent within a dialog. **** use syntax applicable to activity or fragment accordingly

我解决这个问题的方法是不在对话框中调用意图。**** 相应地使用适用于活动或片段的语法

@Override
public void onClick(DialogInterface dialog, int which) {
    checkvariable= true;
    getActivity().finish();
}

@Override
public void onStop() {
    super.onStop();
    if (checkvariable) {
        startActivity(intent); 
    }
}

回答by oguzhan

I got this error but it is resolved interesting. As first, i got this error at api level 17. When i call a thread (AsyncTask or others) without progress dialog then i call an other thread method again using progress dialog, i got that crash and the reason is about usage of progress dialog.

我收到了这个错误,但它的解决很有趣。首先,我在 api 级别 17 收到此错误。当我调用一个没有进度对话框的线程(AsyncTask 或其他线程)时,我再次使用进度对话框调用另一个线程方法,我遇到了崩溃,原因是进度对话框的使用.

In my case, there are two results that;

就我而言,有两个结果;

  • I took show();method of progress dialog before first thread starts then i took dismiss();method of progress dialog before last thread ends.
  • show();在第一个线程开始之前采用了进度对话框的方法,然后dismiss();在最后一个线程结束之前采用了进度对话框的方法。

So :

所以 :

ProgresDialog progressDialog = new ...

//configure progressDialog 

progressDialog.show();

start firstThread {
...
}

...

start lastThread {
...
} 

//be sure to finish threads

progressDialog.dismiss();
  • This is so strange but that error has an ability about destroy itself at least for me :)
  • 这太奇怪了,但这个错误至少对我来说有自我毁灭的能力:)