Android View не подключен к менеджеру окон

У меня есть некоторые из следующих исключений:

java.lang.IllegalArgumentException: View not attached to window manager at android.view.WindowManagerImpl.findViewLocked(WindowManagerImpl.java:355) at android.view.WindowManagerImpl.updateViewLayout(WindowManagerImpl.java:191) at android.view.Window$LocalWindowManager.updateViewLayout(Window.java:428) at android.app.Dialog.onWindowAttributesChanged(Dialog.java:596) at android.view.Window.setDefaultWindowFormat(Window.java:1013) at com.android.internal.policy.impl.PhoneWindow.access$700(PhoneWindow.java:86) at com.android.internal.policy.impl.PhoneWindow$DecorView.drawableChanged(PhoneWindow.java:1951) at com.android.internal.policy.impl.PhoneWindow$DecorView.fitSystemWindows(PhoneWindow.java:1889) at android.view.ViewRoot.performTraversals(ViewRoot.java:727) at android.view.ViewRoot.handleMessage(ViewRoot.java:1633) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:123) at android.app.ActivityThread.main(ActivityThread.java:4338) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:521) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618) at dalvik.system.NativeStart.main(Native Method) 

У меня есть googled и вижу, что это имеет какое-то отношение к всплывающим окнам и поворот экрана, но ссылки на мой код отсутствуют.

Вопросы:

  1. Есть ли способ узнать, когда именно эта проблема происходит?
  2. Кроме поворота экрана, есть другое событие или действие, которое вызывает эту ошибку?
  3. Как я могу предотвратить это?

Solutions Collecting From Web of "Android View не подключен к менеджеру окон"

У меня была эта проблема, когда при изменении ориентации экрана активность завершалась до AsyncTask с завершением диалогового окна выполнения. Я, казалось, решил это, установив диалоговое окно null onPause() а затем проверив это в AsyncTask перед увольнением.

 @Override public void onPause() { super.onPause(); if ((mDialog != null) && mDialog.isShowing()) mDialog.dismiss(); mDialog = null; } 

… в моей AsyncTask:

 protected void onPreExecute() { mDialog = ProgressDialog.show(mContext, "", "Saving changes...", true); } protected void onPostExecute(Object result) { if ((mDialog != null) && mDialog.isShowing()) { mDialog.dismiss(); } } 

Я добавил в манифест для этого действия

 android:configChanges="keyboardHidden|orientation|screenLayout" 

После борьбы с этой проблемой, я, наконец, в конечном итоге с этим обходным путем:

 /** * Dismiss {@link ProgressDialog} with check for nullability and SDK version * * @param dialog instance of {@link ProgressDialog} to dismiss */ public void dismissProgressDialog(ProgressDialog dialog) { if (dialog != null) { if (dialog.isShowing()) { //get the Context object that was used to great the dialog Context context = ((ContextWrapper) dialog.getContext()).getBaseContext(); // if the Context used here was an activity AND it hasn't been finished or destroyed // then dismiss it if (context instanceof Activity) { // Api >=17 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { if (!((Activity) context).isFinishing() && !((Activity) context).isDestroyed()) { dismissWithExceptionHandling(dialog); } } else { // Api < 17. Unfortunately cannot check for isDestroyed() if (!((Activity) context).isFinishing()) { dismissWithExceptionHandling(dialog); } } } else // if the Context used wasn't an Activity, then dismiss it too dismissWithExceptionHandling(dialog); } dialog = null; } } /** * Dismiss {@link ProgressDialog} with try catch * * @param dialog instance of {@link ProgressDialog} to dismiss */ public void dismissWithExceptionHandling(ProgressDialog dialog) { try { dialog.dismiss(); } catch (final IllegalArgumentException e) { // Do nothing. } catch (final Exception e) { // Do nothing. } finally { dialog = null; } } 

Иногда хорошая обработка исключений работает хорошо, если не было лучшего решения этой проблемы.

Если у вас объект Activity висит вокруг, вы можете использовать метод isDestroyed() :

 Activity activity; // ... if (!activity.isDestroyed()) { // ... } 

Это хорошо, если у вас есть не анонимный подкласс AsyncTask который вы используете в разных местах.

Я использую собственный статический класс, который отображает и скрывает диалог. Этот класс используется и другими видами деятельности, а не только одним активом. Теперь проблема, которую вы описали, также мне показалась, и я остался на ночь, чтобы найти решение.

Наконец я представляю вам решение!

Если вы хотите показать или закрыть диалоговое окно, и вы не знаете, какая инициатива инициировала диалог, чтобы коснуться его, тогда для вас будет следующий код.

  static class CustomDialog{ public static void initDialog(){ ... //init code ... } public static void showDialog(){ ... //init code for show dialog ... } /****This is your Dismiss dialog code :D*******/ public static void dismissProgressDialog(Context context) { //Can't touch other View of other Activiy.. //http://stackoverflow.com/questions/23458162/dismiss-progress-dialog-in-another-activity-android if ( (progressdialog != null) && progressdialog.isShowing()) { //is it the same context from the caller ? Log.w("ProgressDIalog dismiss", "the dialog is from"+progressdialog.getContext()); Class caller_context= context.getClass(); Activity call_Act = (Activity)context; Class progress_context= progressdialog.getContext().getClass(); Boolean is_act= ( (progressdialog.getContext()) instanceof Activity )?true:false; Boolean is_ctw= ( (progressdialog.getContext()) instanceof ContextThemeWrapper )?true:false; if (is_ctw) { ContextThemeWrapper cthw=(ContextThemeWrapper) progressdialog.getContext(); Boolean is_same_acivity_with_Caller= ((Activity)(cthw).getBaseContext() == call_Act )?true:false; if (is_same_acivity_with_Caller){ progressdialog.dismiss(); progressdialog = null; } else { Log.e("ProgressDIalog dismiss", "the dialog is NOT from the same context! Can't touch.."+((Activity)(cthw).getBaseContext()).getClass()); progressdialog = null; } } } } } 

На вопрос 1):

Учитывая, что сообщение об ошибке не говорит о том, какая строка вашего кода вызывает проблему, вы можете отслеживать ее с помощью контрольных точек. Точки прерывания приостанавливают выполнение программы, когда программа попадает в определенные строки кода. Добавляя точки останова в критические местоположения, вы можете определить, какая строка кода вызывает сбой. Например, если ваша программа рушится в строке setContentView (), вы можете поставить там точку останова. Когда программа запускается, она приостанавливается до запуска этой строки. Если затем возобновление приводит к сбою программы перед достижением следующей точки останова, вы тогда знаете, что линия, которая убила программу, находилась между двумя точками останова.

Добавление контрольных точек легко, если вы используете Eclipse. Щелкните правой кнопкой мыши по краю слева от кода и выберите «Переключить точку останова». Затем вам нужно запустить приложение в режиме отладки, кнопка, похожая на зеленое насекомое рядом с кнопкой обычного запуска. Когда программа попадает на точку останова, Eclipse переключится на перспективу отладки и покажет вам, в какой строке она ждет. Чтобы запустить программу снова, найдите кнопку «Возобновить», которая выглядит как обычная «Play», но с вертикальной полосой слева от треугольника.

Вы также можете заполнить свое приложение Log.d («Мое приложение», «Некоторая информация здесь, где указано, где находится строка журнала»), который затем отправляет сообщения в окне LogCat Eclipse. Если вы не можете найти это окно, откройте его с помощью Window -> Show View -> Other … -> Android -> LogCat.

Надеюсь, это поможет!

Согласно коду windowManager (ссылка здесь ), это происходит, когда просмотр, который вы пытаетесь обновить (который, вероятно, принадлежит диалогу, но не обязательно) больше не привязан к реальному корню окон.

Как предлагали другие, вы должны проверить статус активности перед выполнением специальных операций в ваших диалогах.

Вот код-релевант, который является причиной проблемы (скопирован из исходного кода Android):

 public void updateViewLayout(View view, ViewGroup.LayoutParams params) { if (!(params instanceof WindowManager.LayoutParams)) { throw new IllegalArgumentException("Params must be WindowManager.LayoutParams"); } final WindowManager.LayoutParams wparams = (WindowManager.LayoutParams)params; view.setLayoutParams(wparams); synchronized (this) { int index = findViewLocked(view, true); ViewRootImpl root = mRoots[index]; mParams[index] = wparams; root.setLayoutParams(wparams, false); } } private int findViewLocked(View view, boolean required) { synchronized (this) { final int count = mViews != null ? mViews.length : 0; for (int i=0; i<count; i++) { if (mViews[i] == view) { return i; } } if (required) { throw new IllegalArgumentException( "View not attached to window manager"); } return -1; } } 

Моя проблема была решена путем включения вращения экрана на моем Android-приложении, которое вызывало у меня проблему теперь отлично работает

Другой вариант – не запускать задачу async до тех пор, пока диалог не будет присоединен к окну, переопределив onAttachedToWindow () в диалоговом окне, таким образом, это всегда будет бесполезно.

Или просто вы можете добавить

 protected void onPreExecute() { mDialog = ProgressDialog.show(mContext, "", "Saving changes...", true, false); } 

Что сделает ProgressDialog не отмененным

Когда вы объявляете активность в манифесте, вам нужен андроид: configChanges = "orientation"

пример:

 <activity android:theme="@android:style/Theme.Light.NoTitleBar" android:configChanges="orientation" android:label="traducción" android:name=".PantallaTraductorAppActivity"></activity> 

Почему бы не попытаться поймать, вот так:

 protected void onPostExecute(Object result) { try { if ((mDialog != null) && mDialog.isShowing()) { mDialog.dismiss(); } } catch (Exception ex) { Log.e(TAG, ex.getMessage(), ex); } }