Просмотр не привязан к краху оконного менеджера

Я использую ACRA для сообщения об авариях приложений. Я получаю сообщение « View not attached to window manager сообщению об ошибке View not attached to window manager и думал, что исправил его, обернув pDialog.dismiss(); В выражении if:

 if (pDialog!=null) { if (pDialog.isShowing()) { pDialog.dismiss(); } } 

Он уменьшил количество View not attached to window manager сбоям View not attached to window manager я получаю, но я все еще получаю некоторые, и я не уверен, как его решить.

Сообщение об ошибке:

 java.lang.IllegalArgumentException: View not attached to window manager at android.view.WindowManagerGlobal.findViewLocked(WindowManagerGlobal.java:425) at android.view.WindowManagerGlobal.removeView(WindowManagerGlobal.java:327) at android.view.WindowManagerImpl.removeView(WindowManagerImpl.java:83) at android.app.Dialog.dismissDialog(Dialog.java:330) at android.app.Dialog.dismiss(Dialog.java:312) at com.package.class$LoadAllProducts.onPostExecute(class.java:624) at com.package.class$LoadAllProducts.onPostExecute(class.java:1) at android.os.AsyncTask.finish(AsyncTask.java:631) at android.os.AsyncTask.access$600(AsyncTask.java:177) at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:644) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:176) at android.app.ActivityThread.main(ActivityThread.java:5419) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:525) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1046) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:862) at dalvik.system.NativeStart.main(Native Method) 

Фрагмент кода:

 class LoadAllProducts extends AsyncTask<String, String, String> { /** * Before starting background thread Show Progress Dialog * */ @Override protected void onPreExecute() { super.onPreExecute(); pDialog = new ProgressDialog(CLASS.this); pDialog.setMessage("Loading. Please wait..."); pDialog.setIndeterminate(false); pDialog.setCancelable(false); pDialog.show(); } /** * getting All products from url * */ protected String doInBackground(String... args) { // Building Parameters doMoreStuff("internet"); return null; } /** * After completing background task Dismiss the progress dialog * **/ protected void onPostExecute(String file_url) { // dismiss the dialog after getting all products if (pDialog!=null) { if (pDialog.isShowing()) { pDialog.dismiss(); //This is line 624! } } something(note); } } - class LoadAllProducts extends AsyncTask<String, String, String> { /** * Before starting background thread Show Progress Dialog * */ @Override protected void onPreExecute() { super.onPreExecute(); pDialog = new ProgressDialog(CLASS.this); pDialog.setMessage("Loading. Please wait..."); pDialog.setIndeterminate(false); pDialog.setCancelable(false); pDialog.show(); } /** * getting All products from url * */ protected String doInBackground(String... args) { // Building Parameters doMoreStuff("internet"); return null; } /** * After completing background task Dismiss the progress dialog * **/ protected void onPostExecute(String file_url) { // dismiss the dialog after getting all products if (pDialog!=null) { if (pDialog.isShowing()) { pDialog.dismiss(); //This is line 624! } } something(note); } } 

Manifest:

  <activity android:name="pagename.CLASS" android:configChanges="keyboard|keyboardHidden|orientation|screenSize|screenLayout" android:label="@string/name" > </activity> Размер  <activity android:name="pagename.CLASS" android:configChanges="keyboard|keyboardHidden|orientation|screenSize|screenLayout" android:label="@string/name" > </activity> 

Что мне не хватает, чтобы остановить этот крах?

Solutions Collecting From Web of "Просмотр не привязан к краху оконного менеджера"

Как воспроизвести ошибку:

  1. Включите эту опцию на своем устройстве: Settings -> Developer Options -> Don't keep Activities .
  2. Нажмите кнопку «Домой» во время выполнения AsyncTask и показывается ProgressDialog .

ОС Android уничтожит действие, как только оно будет скрыто. Когда onPostExecute называется Activity будет находиться в состоянии «завершения», и ProgressDialog не будет привязан к Activity .

Как это исправить:

  1. Проверьте состояние активности в методе onPostExecute .
  2. onDestroy ProgressDialog в методе onDestroy . В противном случае будет android.view.WindowLeaked исключение android.view.WindowLeaked . Это исключение обычно происходит из диалогов, которые все еще активны при завершении работы.

Попробуйте этот фиксированный код:

 public class YourActivity extends Activity { <...> private void showProgressDialog() { if (pDialog == null) { pDialog = new ProgressDialog(StartActivity.this); pDialog.setMessage("Loading. Please wait..."); pDialog.setIndeterminate(false); pDialog.setCancelable(false); } pDialog.show(); } private void dismissProgressDialog() { if (pDialog != null && pDialog.isShowing()) { pDialog.dismiss(); } } @Override protected void onDestroy() { dismissProgressDialog(); super.onDestroy(); } class LoadAllProducts extends AsyncTask<String, String, String> { /** * Before starting background thread Show Progress Dialog * */ @Override protected void onPreExecute() { showProgressDialog(); } /** * getting All products from url * */ protected String doInBackground(String... args) { doMoreStuff("internet"); return null; } /** * After completing background task Dismiss the progress dialog * **/ protected void onPostExecute(String file_url) { if (YourActivity.this.isDestroyed()) { // or call isFinishing() if min sdk version < 17 return; } dismissProgressDialog(); something(note); } } } - public class YourActivity extends Activity { <...> private void showProgressDialog() { if (pDialog == null) { pDialog = new ProgressDialog(StartActivity.this); pDialog.setMessage("Loading. Please wait..."); pDialog.setIndeterminate(false); pDialog.setCancelable(false); } pDialog.show(); } private void dismissProgressDialog() { if (pDialog != null && pDialog.isShowing()) { pDialog.dismiss(); } } @Override protected void onDestroy() { dismissProgressDialog(); super.onDestroy(); } class LoadAllProducts extends AsyncTask<String, String, String> { /** * Before starting background thread Show Progress Dialog * */ @Override protected void onPreExecute() { showProgressDialog(); } /** * getting All products from url * */ protected String doInBackground(String... args) { doMoreStuff("internet"); return null; } /** * After completing background task Dismiss the progress dialog * **/ protected void onPostExecute(String file_url) { if (YourActivity.this.isDestroyed()) { // or call isFinishing() if min sdk version < 17 return; } dismissProgressDialog(); something(note); } } } 

Проблема может заключаться в том, что Activity finished или progress of finishing .

Добавьте проверку isFinishing и isFinishing диалог только тогда, когда это false

 if (!YourActivity.this.isFinishing() && pDialog != null) { pDialog.dismiss(); } 

IsFinishing: проверьте, выполняется ли эта активность в процессе финиша, либо потому, что вы вызвали ее finish либо кто-то попросил ее закончить.

Посмотрите, как работает здесь код:

После вызова задачи Async задача async выполняется в фоновом режиме. Что желательно. Теперь эта задача Async имеет диалог прогресса, который привязан к Activity, если вы спросите, как это увидеть, см. Код:

 pDialog = new ProgressDialog(CLASS.this); 

Вы передаете Class.this как контекст аргумента. Таким образом, диалог «Прогресс» все еще привязан к действию.

Теперь рассмотрим сценарий: если мы попытаемся закончить операцию с использованием метода finish (), в то время как выполняется асинхронная задача, это точка, в которой вы пытаетесь получить доступ к progess bar связанному с активностью, т. progess bar когда активность отсутствует Больше там.

Следовательно, вы получаете:

 java.lang.IllegalArgumentException: View not attached to window manager 

,

Решение этого:

1) Убедитесь, что диалоговое окно отклонено или отменено до завершения операции.

2) Завершите действие, только после отклонения диалогового окна, то есть задача async завершена.

Основываясь на ответе @erakitin, но также совместимом с версиями Android <API уровня 17. С грустью Activity.isDestroyed () поддерживается только с уровня API 17, поэтому, если вы ориентируетесь на более старый уровень API, как и я, вам придется Проверьте это самостоятельно. После этого не было видно, что View not attached to window manager исключению View not attached to window manager .

Пример кода

 public class MainActivity extends Activity { private TestAsyncTask mAsyncTask; private ProgressDialog mProgressDialog; private boolean mIsDestroyed; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); if (condition) { mAsyncTask = new TestAsyncTask(); mAsyncTask.execute(); } } @Override protected void onResume() { super.onResume(); if (mAsyncTask != null && mAsyncTask.getStatus() != AsyncTask.Status.FINISHED) { Toast.makeText(this, "Still loading", Toast.LENGTH_LONG).show(); return; } } @Override protected void onDestroy() { super.onDestroy(); mIsDestroyed = true; if (mProgressDialog != null && mProgressDialog.isShowing()) { mProgressDialog.dismiss(); } } public class TestAsyncTask extends AsyncTask<Void, Void, AsyncResult> { @Override protected void onPreExecute() { super.onPreExecute(); mProgressDialog = ProgressDialog.show(MainActivity.this, "Please wait", "doing stuff.."); } @Override protected AsyncResult doInBackground(Void... arg0) { // Do long running background stuff return null; } @Override protected void onPostExecute(AsyncResult result) { // Use MainActivity.this.isDestroyed() when targeting API level 17 or higher if (mIsDestroyed)// Activity not there anymore return; mProgressDialog.dismiss(); // Handle rest onPostExecute } } } 
 @Override public void onPause() { super.onPause(); if(pDialog != null) pDialog .dismiss(); pDialog = null; } 

См. Это .

Переопределить onConfigurationChanged и отклонить диалог прогресса. Если диалог прогресса создается в портрете и отменяется в ландшафте, он будет бросать View, не привязанный к ошибке диспетчера окон.

Также остановите индикатор выполнения и остановите задачу async в onPause (), onBackPressed и onDestroy.

 if(asyncTaskObj !=null && asyncTaskObj.getStatus().equals(AsyncTask.Status.RUNNING)){ asyncTaskObj.cancel(true); } 

Переопределить onDestroy активности и отклонить ваш диалог и сделать его нулевым

 protected void onDestroy () { if(mProgressDialog != null) if(mProgressDialog.isShowing()) mProgressDialog.dismiss(); mProgressDialog= null; } 

Может быть, вы инициализируете pDialog глобально, затем удалите его и настройте свой взгляд или диалог локально. У меня такая же проблема, я сделал это, и моя проблема решена. Надеюсь, это сработает для вас.

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

 /** * After completing background task Dismiss the progress dialog * **/ protected void onPostExecute(String file_url) { try { if (pDialog!=null) { pDialog.dismiss(); //This is line 624! } } catch (Exception e) { // do nothing } something(note); } - /** * After completing background task Dismiss the progress dialog * **/ protected void onPostExecute(String file_url) { try { if (pDialog!=null) { pDialog.dismiss(); //This is line 624! } } catch (Exception e) { // do nothing } something(note); } 

У меня есть способ воспроизвести это исключение.

Я использую 2 AsyncTask . Один делает длинную задачу, а другой выполняет короткую задачу. После завершения короткой задачи вызовите finish() . Когда долгая задача завершена и вызывается Dialog.dismiss() , он Dialog.dismiss() .

Вот мой пример кода:

 public class MainActivity extends Activity { private static final String TAG = "MainActivity"; private ProgressDialog mProgressDialog; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Log.d(TAG, "onCreate"); new AsyncTask<Void, Void, Void>(){ @Override protected void onPreExecute() { mProgressDialog = ProgressDialog.show(MainActivity.this, "", "plz wait...", true); } @Override protected Void doInBackground(Void... nothing) { try { Log.d(TAG, "long thread doInBackground"); Thread.sleep(20000); } catch (InterruptedException e) { e.printStackTrace(); } return null; } @Override protected void onPostExecute(Void result) { Log.d(TAG, "long thread onPostExecute"); if (mProgressDialog != null && mProgressDialog.isShowing()) { mProgressDialog.dismiss(); mProgressDialog = null; } Log.d(TAG, "long thread onPostExecute call dismiss"); } }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); new AsyncTask<Void, Void, Void>(){ @Override protected Void doInBackground(Void... params) { try { Log.d(TAG, "short thread doInBackground"); Thread.sleep(5000); } catch (InterruptedException e) { e.printStackTrace(); } return null; } @Override protected void onPostExecute(Void aVoid) { super.onPostExecute(aVoid); Log.d(TAG, "short thread onPostExecute"); finish(); Log.d(TAG, "short thread onPostExecute call finish"); } }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); } @Override protected void onDestroy() { super.onDestroy(); Log.d(TAG, "onDestroy"); } } 

Вы можете попробовать это и выяснить, как лучше всего решить эту проблему. Из моего исследования есть по крайней мере 4 способа исправить это:

  1. @ Ответ эракитина: вызов isFinishing() чтобы проверить состояние активности
  2. @ Ответ Капе: установить флаг для проверки состояния активности
  3. Используйте try / catch для его обработки.
  4. Вызовите AsyncTask.cancel(false) в onDestroy() . Это предотвратит выполнение onPostExecute() но вместо этого выполнит onCancelled() .
    Примечание: onPostExecute() прежнему будет выполнять даже вызывать AsyncTask.cancel(false) на более старой ОС Android, например, Android 2.XX

Вы можете выбрать лучший для вас.

лучшее решение. Проверьте первый контекст – контекст активности или контекст приложения, если контекст активности, а затем только проверка активности завершена или нет, затем вызовите dialog.show() или dialog.dismiss();

См. Пример кода ниже … надеюсь, что это будет полезно!

Диалоговое окно

 if (context instanceof Activity) { if (!((Activity) context).isFinishing()) dialog.show(); } 

Диалог «Отклонить»

 if (context instanceof Activity) { if (!((Activity) context).isFinishing()) dialog.dismiss(); } 

Если вы хотите добавить дополнительные проверки, добавьте dialog.isShowing() или dialog !-null используя условие && .

Для Dialog созданного в Fragment , я использую следующий код:

 ProgressDialog myDialog = new ProgressDialog(getActivity()); myDialog.setOwnerActivity(getActivity()); ... Activity activity = myDialog.getOwnerActivity(); if( activity!=null && !activity.isFinishing()) { myDialog.dismiss(); } 

Я использую этот шаблон для рассмотрения случая, когда Fragment может быть отделен от Activity .

Во-первых, причиной сбоя является индекс decorView -1, мы можем узнать его из исходного кода Android, есть фрагмент кода:

Класс: android.view.WindowManagerGlobal

Файл: WindowManagerGlobal.java

 private int findViewLocked(View view, boolean required) { final int index = mViews.indexOf(view); //here, view is decorView,comment by OF if (required && index < 0) { throw new IllegalArgumentException("View=" + view + " not attached to window manager"); } return index; } 

Поэтому мы получаем разрешение на выполнение, просто оцените индекс decorView, если он больше 0, то продолжайте или просто вернитесь и откажитесь от увольнения, как показано ниже:

 try { Class<?> windowMgrGloable = Class.forName("android.view.WindowManagerGlobal"); try { Method mtdGetIntance = windowMgrGloable.getDeclaredMethod("getInstance"); mtdGetIntance.setAccessible(true); try { Object windownGlobal = mtdGetIntance.invoke(null,null); try { Field mViewField = windowMgrGloable.getDeclaredField("mViews"); mViewField.setAccessible(true); ArrayList<View> mViews = (ArrayList<View>) mViewField.get(windownGlobal); int decorViewIndex = mViews.indexOf(pd.getWindow().getDecorView()); Log.i(TAG,"check index:"+decorViewIndex); if (decorViewIndex < 0) { return; } } catch (NoSuchFieldException e) { e.printStackTrace(); } } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } catch (NoSuchMethodException e) { e.printStackTrace(); } } catch (ClassNotFoundException e) { e.printStackTrace(); } if (pd.isShowing()) { pd.dismiss(); }