Какова эта ошибка и почему это происходит?
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)
Вы пытаетесь показать диалоговое окно после выхода из Activity.
[EDIT]
Этот вопрос является одним из лучших поисков в Google для разработчиков Android, поэтому добавление нескольких важных моментов из комментариев, которые могут быть более полезными для будущего исследователя, без углубленного обсуждения комментариев.
Ответ 1:
Вы пытаетесь показать диалоговое окно после выхода из Activity.
Ответ 2
В некоторых случаях эта ошибка может быть немного ошибочной (хотя ответ по-прежнему полностью точен), то есть в моем случае необработанное исключение было выброшено в AsyncTask, что вызвало Активность для выключения, затем открытый прогрессдиалог вызвал это Исключение.. так что "реальное" исключение было немного раньше в журнале
Ответ 3
Отклонить вызов() в экземпляре диалога, который вы создали, прежде чем выйти из Активность, например. in onPause() или onDestroy()
Решение состоит в вызове dismiss()
в Dialog
, созданном вами в viewP.java:183
, перед выходом из Activity
, например. в onPause()
. Все Window
s & Dialog
должны быть закрыты перед тем, как оставить Activity
.
Если вы используете AsyncTask
, возможно, сообщение журнала может быть обманным. Если вы посмотрите в своем журнале, вы можете найти еще одну ошибку, возможно, одну из ваших методов doInBackground()
вашего AsyncTask
, которая заставит ваш текущий Activity
взорваться, и, как только вернется AsyncTask
. Знаете, вы знаете все остальное. Некоторые другие пользователи уже объяснили, что здесь: -)
doInBackground
класса AsyncTask
но без объявления его в файле AndroidManifest
с помощью свойства android:name
например: android:name="my.package.MyApplicationClass"
. Хорошей практикой при использовании AsyncTask
всегда является создание экземпляра вашего оповещения внутри метода onPreExecute
и отклонение его на onPostExecute
.
Я вызвал эту ошибку, ошибочно называя hide()
вместо dismiss()
на AlertDialog
.
Вы можете получить это исключение просто простой/немой ошибкой, например (случайно), вызвав finish()
после отображения AlertDialog
, если вы пропустите выражение о вызове break в инструкции switch...
@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
все еще отображается!
Поэтому, когда вы внимательно смотрите на код, ища проблемы с плохой резьбой или сложное кодирование и т.д., не упускайте из виду лес для деревьев. Иногда это может быть просто что-то такое же простое и немое, как недостающий оператор break.:)
Эта проблема возникает при попытке показать диалоговое окно после выхода из Activity.
Я просто решил эту проблему, просто записав следующий код:
@Override
public void onDestroy(){
super.onDestroy();
if ( progressDialog!=null && progressDialog.isShowing() ){
progressDialog.cancel();
}
}
В принципе, из какого класса вы начали progressDialog, переопределите метод onDestroy и сделайте это. Он решил проблему "Проблема с утечкой окна".
Ответы на этот вопрос были правильными, но немного смущающими для меня, чтобы понять, почему. После игры около 2 часов причина этой ошибки (в моем случае) ударила меня:
Вы уже знаете, начиная с чтения других ответов, что X has leaked window DecorView@d9e6131[]
означает, что диалог закрыт, когда ваше приложение закрыто. Но почему?
Может быть, ваше приложение разбилось по какой-то другой причине, пока ваш диалог был открыт
Это приведет к закрытию вашего приложения из-за некоторой ошибки в вашем коде, что приведет к открытию диалогового окна одновременно с закрытием приложения из-за другой ошибки.
Итак, просмотрите свое логическое. Решите первую ошибку, а затем вторая ошибка решит себя
Одна ошибка вызывает другую, которая вызывает другую, как DOMINOS!
Недавно я столкнулся с той же проблемой.
Причина этой проблемы заключается в том, что закрытие операции перед диалогом отменяется. Существуют разные причины для того, чтобы это произошло. Те, о которых упоминалось выше, также верны.
Я попал в ситуацию, потому что в потоке я вызывал функцию, которая бросала исключение. Из-за чего окно было уволено и, следовательно, исключение.
Отключить диалог, когда действие уничтожает
@Override
protected void onDestroy()
{
super.onDestroy();
if (pDialog!=null && pDialog.isShowing()){
pDialog.dismiss();
}
}
Это может помочь.
if (! isFinishing()) {
dialog.show();
}
Я получал эти журналы в приложении для видеопроигрывателя. Эти сообщения были брошены, когда видеопроигрыватель был закрыт. Интересно, что я использовал эти журналы один раз в нескольких сериях случайным образом. Также мое приложение не участвует ни в одном 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
".
У меня было такое же непонятное сообщение об ошибке, и я понятия не имел, почему. Учитывая подсказки из предыдущих ответов, я изменил свои вызовы без GUI на mDialog.finish(), чтобы быть mDialog.dismiss(), и ошибки исчезли. Это не повлияло на поведение моего виджета, но оно было сбито с толку и вполне могло помешать важной утечке памяти.
У меня была такая же проблема, и я нашел эту страницу, и, хотя моя ситуация была другая, я назвал finish
из блока if
прежде чем он определил окно предупреждения.
Таким образом, просто вызов dismiss
не будет работать (как это еще не было сделано), но после прочтения ответа Алекса Воловой и осознания этого было поле оповещения, вызывающее его. Я попытался добавить оператор return сразу после финиша внутри, if
блок и это исправило проблему.
Я подумал, как только ты позвонил, он остановил все и закончил там, но это не так. Кажется, он доходит до конца блока кода, а затем заканчивается.
Итак, если вы хотите реализовать ситуацию, когда иногда она заканчивается, прежде чем делать какой-то код, вам нужно поставить оператор возврата сразу после финиша, или он продолжит движение и будет действовать так, как будто конец был вызван в конце блок кода не там, где вы его назвали. Вот почему я получал все эти странные ошибки.
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();
и, следовательно, он сказал бы, что окно просочилось, закончив сразу после того, как вы запустили диалог, хотя это не так, все же это так.
Я думал, что добавлю это как здесь, так как это показывает, что команда финиша действовала по-другому, тогда я подумал, что это так, и я думаю, есть другие люди, которые думают так же, как и я, прежде чем я это обнаружил.
Это не ответ на вопрос, но он имеет отношение к теме.
Если действие определило атрибут в манифесте
android:noHistory="true"
то после выполнения onPause() контекст активности теряется. Таким образом, все представление, использующее этот контекст, может привести к этой ошибке.
progessdialog.show()
.. и progressdialog.hide()
в asynctask
того же действия вместо onPause()
из activity
?? взгляните на мою проблему ... stackoverflow.com/questions/39332880/…
Не только пытайтесь показать предупреждение, но также можно вызвать, когда вы закончите конкретный экземпляр активности и попытаетесь запустить новую активность/службу или попытаться ее остановить.
Пример:
OldActivity instance;
oncreate() {
instance=this;
}
instance.finish();
instance.startActivity(new Intent(ACTION_MAIN).setClass(instance, NewActivity.class));
Это случилось со мной, когда я использую ProgressDialog
в AsyncTask
. На самом деле я использую метод hide()
в onPostExecute
. Основываясь на ответе @Alex Volovoy, мне нужно использовать dismiss()
с ProgressDialog
, чтобы удалить его в onPostExecute и сделать его.
progressDialog.hide(); // Don't use it, it gives error
progressDialog.dismiss(); // Use it
AsyncTask
и вы показываете Dialog
, то происходит что-то, что заставляет Activity
вызывать onPause()
(может быть, какая-то логика в самом AsyncTask, например, слушатель, тогда он будет просачиваться. 2) Как упоминалось выше, Dialog
который был создан с этим Context
Activity
никогда не отклоняется, и Activity
продолжается.
Это может быть, если у вас есть ошибка в функции 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();
Попробуйте этот код:
public class Sample extends Activity(){
@Override
public void onCreate(Bundle instance){
}
@Override
public void onStop() {
super.onStop();
progressdialog.dismiss(); // try this
}
}
progressdialog.dismiss();
это может создать NullPointerException.
Была проблема, когда я закончил действие, когда ProgressDialog все еще показывался.
Итак, сначала скройте диалоговое окно, а затем завершите действие.
Ошибка "Activity has leaked window that was originally added...
" возникает, когда вы пытаетесь показать предупреждение после Activity
эффективно finished
.
У вас есть два варианта: AFAIK:
dismiss()
на dialog
, прежде чем выйдите из своей активности.dialog
в другой поток и запустите его на thread
(независимо от текущего Activity
).Как правило, эта проблема возникает из-за диалога прогресса: вы можете решить эту проблему, используя любой из следующих способов в своей деятельности:
// 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();
}
}
Вы должны сделать Progressdialog
объект в onPreExecute
методе AsyncTask
, и вы должны dismiss
его использовать для метода onPostExecute
.
Лучшее решение - это просто добавить диалог в диалог try catch и reject при возникновении исключения
Просто используйте ниже код
try {
dialog.show();
} catch (Exception e) {
dialog.dismiss();
}
dialog.dismiss()
завершено?, я думаю, что dialog.dismiss()
тоже выдаст ошибку
В моем случае причина заключалась в том, что я забыл включить разрешение в файл манифеста Android.
Как я узнал? Ну, точно так же, как @Bobby говорит в комментарии под принятым ответом, просто прокрутите дальше до ваших журналов, и вы увидите первую причину или событие, которое действительно выбросило исключение. По-видимому, сообщение "Activity имеет просочившееся окно, которое было первоначально добавлено", является только Исключением, результатом которого является первое исключение.
Лучшее решение поставлено перед показом progressbar
или progressDialog
if (getApplicationContext().getWindow().getDecorView().isShown()) {
//Show Your Progress Dialog
}
Исключенные из окна исключения имеют две причины:
1), показывая диалог, когда контекст активности не существует, для его устранения вы должны показать диалог только, что вы уверены, что существует действие:
if(getActivity()!= null && !getActivity().isFinishing()){
Dialog.show();
}
2) не отмените диалог соответствующим образом, чтобы решить использовать этот код:
@Override
public void onDestroy(){
super.onDestroy();
if ( Dialog!=null && Dialog.isShowing() ){
Dialog.dismiss();
}
}
Попробуйте под кодом, он будет работать в любое время, когда вы отпустите диалог прогресса, и он увидит, доступен ли его экземпляр или нет.
try {
if (null != progressDialog && progressDialog.isShowing()) {
progressDialog.dismiss();
progressDialog = null;
}
} catch (Exception e) {
e.printStackTrace();
}
Получил эту ошибку при попытке отобразить поток Toast из Background. Он был разрешен путем запуска кода, связанного с пользовательским интерфейсом, в потоке пользовательского интерфейса
Проблема по мне заключается в том, что вы пытаетесь вызвать диалог сразу после того, как действие завершается, поэтому согласно мне, что вы можете сделать, это дать некоторую задержку с помощью Handler, и вы будете решены, например:
Handler handler=new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
dialog.show();
//or
dialog.dismiss();
}
},100);
if (mActivity != null && !mActivity.isFinishing() && mProgressDialog != null && mProgressDialog.isShowing()) {
mProgressDialog.dismiss();
}
Просто убедитесь, что ваша активность не закрывается неожиданно из-за некоторых исключений, возникающих где-то в вашем коде. Как правило, это происходит в async-задаче, когда активность сталкивается с принудительным закрытием в doinBackground, а затем asynctask возвращает метод onPostexecute.
Возможно, вы использовали findViewById
в активности вместо dialog.findViewById
и впоследствии установили OnClickListener
для null
экземпляра, что, вероятно, вызвало первоначальную ошибку.
Обязательно позвоните this.dialog.show. (Деятельность)
Я тоже сталкивался с этой проблемой некоторое время, но я понял это не из-за dialog
в моем случае из-за ActionMode
. Поэтому, если вы пытаетесь завершить работу, когда открыт ActionMode
, это вызовет эту проблему. В вашей деятельности onPause
закончить действие.
private ActionMode actionMode;
@Override
public void onActionModeStarted(ActionMode mode) {
super.onActionModeStarted(mode);
actionMode = mode;
}
@Override
protected void onPause() {
super.onPause();
if (actionMode != null) actionMode.finish();
}
Я также сталкиваюсь с проблемой WindowLeaked при запуске теста обезьяны. Локальный код ниже.
android.support.v7.app.AppCompatDelegateImplV7$ListMenuDecorView@4334fd40 that was originally added here
android.view.WindowLeaked: Activity com.myapp.MyActivity has leaked window android.support.v7.app.AppCompatDelegateImplV7$ListMenuDecorView@4334fd40 that was originally added here
at android.view.ViewRootImpl.<init>(ViewRootImpl.java:409)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:312)
at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:224)
at android.view.WindowManagerImpl$CompatModeWrapper.addView(WindowManagerImpl.java:149)
at android.view.Window$LocalWindowManager.addView(Window.java:554)
at android.support.v7.app.AppCompatDelegateImplV7.openPanel(AppCompatDelegateImplV7.java:1150)
at android.support.v7.app.AppCompatDelegateImplV7.onKeyUpPanel(AppCompatDelegateImplV7.java:1469)
at android.support.v7.app.AppCompatDelegateImplV7.onKeyUp(AppCompatDelegateImplV7.java:919)
at android.support.v7.app.AppCompatDelegateImplV7.dispatchKeyEvent(AppCompatDelegateImplV7.java:913)
at android.support.v7.app.AppCompatDelegateImplBase$AppCompatWindowCallbackBase.dispatchKeyEvent(AppCompatDelegateImplBase.java:241)
at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:2009)
at android.view.ViewRootImpl.deliverKeyEventPostIme(ViewRootImpl.java:3929)
at android.view.ViewRootImpl.deliverKeyEvent(ViewRootImpl.java:3863)
at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:3420)
at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:4528)
at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:4506)
at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:4610)
at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:171)
at android.os.MessageQueue.nativePollOnce(Native Method)
at android.os.MessageQueue.next(MessageQueue.java:125)
at android.os.Looper.loop(Looper.java:124)
at android.app.ActivityThread.main(ActivityThread.java:4898)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:511)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1008)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:775)
at dalvik.system.NativeStart.main(Native Method)
Моя активность - AppCompatActivity.And я переделал его с приведенным ниже кодом в Activity.
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
// added by sunhang : intercept menu key to resove a WindowLeaked error in monkey-test.
if (event.getKeyCode() == KeyEvent.KEYCODE_MENU) {
return true;
}
return super.dispatchKeyEvent(event);
}
У меня есть другое решение для этого, и я хотел бы знать, если это кажется вам действительным: вместо увольнения в onDestroy, который, кажется, является ведущим решением, я расширяю ProgressDialog...
public class MyProgressDialog extends ProgressDialog {
private boolean isDismissed;
public MyProgressDialog(Context context) {
super(context);
}
@Override
public void onDetachedFromWindow() {
super.onDetachedFromWindow();
dismiss();
}
@Override
public void dismiss() {
if (isDismissed) {
return;
}
try {
super.dismiss();
} catch (IllegalArgumentException e) {
// ignore
}
isDismissed = true;
}
Это предпочтительнее, AFAIC, потому что вам не нужно удерживать диалог выполнения в качестве участника, просто стрелять (показывать) и забыть
У меня такая же проблема. ошибка была не в Dialog
, а в EditText
. Я пытался изменить значение EditText
внутри Assynctask
. единственное, что я мог решить, - это создать новый runnable
.
runOnUiThread(new Runnable(){
@Override
public void run() {
...
}
});
Я использовал диалог `onError видеопроигрывателя и вместо того, чтобы сходить с ума (я протестировал все эти решения)
Я выбрал DialogFragment
http://developer.android.com/reference/android/app/DialogFragment.html.
Вы можете вернуть создание строителя во внутреннем классе DialogFragment
, просто переопределить onCreateDialog