这是什么错误,为什么会发生?
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)
您在退出活动后尝试显示对话框。
[编辑]
这个问题是google for android开发者的热门搜索之一,因此从评论中添加了一些重要的观点,这可能对未来的调查人员更有帮助,而无需进行深入的评论对话。
答案1:
您在退出活动后尝试显示对话框。
答案2
在某些情况下这个错误可能有点误导(尽管答案仍然是完全准确的) - 即在我的情况下,在AsyncTask中抛出了未处理的异常,导致Activity关闭,然后打开progressdialog导致此异常..所以“真正的”例外在日志中早一点
答案3
在退出Activity之前,在您创建的Dialog实例上调用dismiss(),例如在onPause()或onDestroy()
活动销毁时关闭对话框
@Override
protected void onDestroy()
{
super.onDestroy();
if (pDialog!=null && pDialog.isShowing()){
pDialog.dismiss();
}
}
我有同样晦涩的错误信息,不知道为什么。根据之前答案的线索,我将我的非GUI调用mDialog.finish()更改为mDialog.dismiss(),错误消失了。这并没有影响我的小部件的行为,但它令人不安,很可能已经标记了一个重要的内存泄漏。
我在我的视频播放器应用程序中获取这些日志。视频播放器关闭时抛出这些消息。有趣的是,我曾经以随机方式在几次运行中获取这些日志。我的申请也不涉及任何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
”日志错误问题。
我遇到了同样的问题并找到了这个页面,虽然我的情况不同,但在定义警报框之前,我从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();
之后调用了它,因此它会说你在对话框出现之后就完成了窗口的泄漏,即使事实并非如此,它仍然认为是这样的。
我想我会在这里添加这个,因为这显示了完成命令的行为不同然后我认为它确实如此,我猜有其他人在我发现这个之前就像我一样。
这不是问题的答案,但它与该主题相关。
如果活动在Manifest中定义了一个属性
android:noHistory="true"
然后在执行onPause()之后,活动的上下文就会丢失。因此,使用此上下文的所有视图都可能会出现此错误。
不仅尝试显示警报,还可以在完成特定活动实例并尝试启动新活动/服务或尝试停止时调用它。
例:
OldActivity instance;
oncreate() {
instance=this;
}
instance.finish();
instance.startActivity(new Intent(ACTION_MAIN).setClass(instance, NewActivity.class));
如果仍然显示ProgressDialog,我在完成活动的问题。
首先隐藏对话框,然后完成活动。
试试这段代码:
public class Sample extends Activity(){
@Override
public void onCreate(Bundle instance){
}
@Override
public void onStop() {
super.onStop();
progressdialog.dismiss(); // try this
}
}
这可能是因为你在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();
当我在ProgressDialog
使用AsyncTask
时,这发生在我身上。其实我在hide()
使用onPostExecute
方法。根据@Alex Volovoy的答案,我需要使用dismiss()
和ProgressDialog
在onPostExecute中删除它并完成它。
progressDialog.hide(); // Don't use it, it gives error
progressDialog.dismiss(); // Use it
解决方法是在退出dismiss()
之前调用你在Dialog
创建的viewP.java:183
上的Activity
,例如:在onPause()
。在离开Window
之前,所有Dialog
s和Activity
s应该关闭。
当Activity has leaked window that was originally added...
实际上是Activity
后尝试显示警报时,会出现“finished
”错误。
你有两个选择AFAIK:
dismiss()
上调用dialog
。dialog
放在另一个线程中并在thread
上运行(独立于当前的activity
)。你必须在Progressdialog
的onPreExecute
方法中制作AsyncTask
对象,你应该在dismiss
方法上使用onPostExecute
。
通常由于进度对话框而发生此问题:您可以通过在活动中使用以下任一方法来解决此问题:
// 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();
}
}
在我的情况下,原因是我忘了在Android清单文件中包含权限。
我是怎么知道的?好吧,就像@Bobby在接受的答案下面的评论中说的那样,只需向上滚动到你的日志,你就会看到真正抛出异常的第一个原因或事件。显然,消息“活动已泄漏最初添加的窗口”只是一个异常,它是由第一个异常引起的。
最佳解决方案是在发生异常时在try catch和dismiss对话框中添加对话框
只需使用下面的代码
try {
dialog.show();
} catch (Exception e) {
dialog.dismiss();
}
尝试下面的代码,它将在您解除进度对话框的任何时候工作,它将查看其实例是否可用。
try {
if (null != progressDialog && progressDialog.isShowing()) {
progressDialog.dismiss();
progressDialog = null;
}
} catch (Exception e) {
e.printStackTrace();
}
窗口泄露异常有两个原因:
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();
}
}
在展示progressbar
或progressDialog
之前,最好的解决方案是这个
if (getApplicationContext().getWindow().getDecorView().isShown()) {
//Show Your Progress Dialog
}
由于代码中某处出现了一些异常,请确保您的活动未意外关闭。通常,当活动面临强制关闭doinBackground方法然后asynctask返回onPostexecute方法时,它发生在异步任务中。
if (mActivity != null && !mActivity.isFinishing() && mProgressDialog != null && mProgressDialog.isShowing()) {
mProgressDialog.dismiss();
}
如果您使用AsyncTask
,可能该日志消息可能具有欺骗性。如果你查看你的日志,你可能会发现另一个错误,可能是你的doInBackground()
的AsyncTask
方法中的一个,这使你当前的Activity
爆炸,因此一旦AsyncTask
回来..好吧,你知道其余的。其他一些用户已在此处解释:-)
根据我的问题是你试图在一个活动完成后立即调用一个对话框,所以根据我你可以做的是使用Handler给你一些延迟,你的问题将解决,例如:
Handler handler=new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
dialog.show();
//or
dialog.dismiss();
}
},100);
我错误地在hide()
上调用dismiss()
而不是AlertDialog
来触发此错误。
你可以通过一个简单/愚蠢的错误得到这个例外,例如,如果你在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
仍然显示!
因此,当你专心盯着代码,寻找糟糕的线程问题或复杂的编码等时,不要忽视森林中的树木。有时它可能只是一个简单而愚蠢的东西,就像一个缺失的断言。 :)
在退出活动后尝试显示对话框时出现此问题。
我刚刚通过写下以下代码解决了这个问题:
@Override
public void onDestroy(){
super.onDestroy();
if ( progressDialog!=null && progressDialog.isShowing() ){
progressDialog.cancel();
}
}
基本上,从哪个类开始progressDialog,覆盖onDestroy方法并以这种方式执行。它解决了“活动已泄露窗口”的问题。
我最近遇到了同样的问题。
这个问题背后的原因是在关闭对话框之前关闭了活动。上述情况有多种原因。上面帖子中提到的那些也是正确的。
我遇到了一种情况,因为在线程中,我正在调用一个抛出异常的函数。因为窗户被解雇,因此例外。
这可能有所帮助。
if (! isFinishing()) {
dialog.show();
}