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()
mol*_*arm 391
解决的办法是打电话给dismiss()
在Dialog
您创建viewP.java:183
退出之前Activity
,例如onPause()
.所有的Window
s&Dialog
s应该在离开之前关闭Activity
.
ggo*_*eze 107
如果您正在使用AsyncTask
,可能该日志消息可能具有欺骗性.如果你在你的日志中查找,你可能会发现另一个错误,可能是你的doInBackground()
方法中的一个错误,AsyncTask
即让你的当前Activity
爆炸,因此一旦AsyncTask
回来......好吧,你知道其余的.其他一些用户已在此处解释:-)
Mar*_*lip 66
我被误调用触发此错误的hide()
,而不是dismiss()
上AlertDialog
.
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!
Tus*_*har 19
我最近遇到了同样的问题.
这个问题背后的原因是在关闭对话框之前关闭了活动.上述情况有多种原因.上面帖子中提到的那些也是正确的.
我遇到了一种情况,因为在线程中,我正在调用一个抛出异常的函数.因为窗户被解雇,因此例外.
san*_*ndy 14
这可能有所帮助.
if (! isFinishing()) {
dialog.show();
}
Run Code Online (Sandbox Code Playgroud)
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)
覆盖OnPause
with调用mVideoView.pause()
和设置visibility
为GONE
.这样我就可以解决" 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();
,因此它会说你在对话框出现之后就完成了窗口的泄漏,即使这是不是这样,它仍然认为是.
我想我会在这里添加这个,因为这显示了完成命令的行为不同然后我认为它做了,我猜有其他人在我发现这个之前的想法和我做的一样.
这不是问题的答案,但它与该主题相关.
如果活动在Manifest中定义了一个属性
android:noHistory="true"
Run Code Online (Sandbox Code Playgroud)
然后在执行onPause()之后,活动的上下文就会丢失.因此,使用此上下文的所有视图都可能会出现此错误.
当您确实想关闭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)
不仅尝试显示警报,还可以在完成特定活动实例并尝试启动新活动/服务或尝试停止时调用它.
例:
OldActivity instance;
oncreate() {
instance=this;
}
instance.finish();
instance.startActivity(new Intent(ACTION_MAIN).setClass(instance, NewActivity.class));
Run Code Online (Sandbox Code Playgroud)
Activity has leaked window that was originally added...
当您尝试在Activity
有效后显示警报时,会出现" "错误finished
.
你有两个选择AFAIK:
dismiss()
的dialog
实际退出你的活动之前.dialog
置于不同的线程并在其上运行thread
(独立于当前activity
).试试这段代码:
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)
这可能是因为你在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)
这发生在我身上,当我使用ProgressDialog
在AsyncTask
.其实我正在使用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)
通常,此问题是由于进度对话框而发生的:您可以通过在活动中使用以下任何一种方法来解决此问题:
// 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)
它可能对访问此问题的人有所帮助。
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
发起)不处于 isFinishing
或isDestroyed
状态。有时,当对话框托管活动即将破坏并且我们面临“泄漏窗口”问题时,我们会尝试打开对话框
dialog.isShowing
检查对话框之前的show()
对话框状态dismiss()
。
归档时间: |
|
查看次数: |
507534 次 |
最近记录: |