Java.lang.IllegalArgumentException: просмотр не подключен к менеджеру окон

У меня есть активность, которая запускает AsyncTask и показывает диалог выполнения на время работы. Активность объявлена ​​НЕ воссозданной поворотом или слайдом клавиатуры.

<activity android:name=".MyActivity" android:label="@string/app_name" android:configChanges="keyboardHidden|orientation" > <intent-filter> </intent-filter> </activity> 

После завершения задачи я отключаю диалог, но на некоторых телефонах (framework: 1.5, 1.6) такая ошибка возникает:

 java.lang.IllegalArgumentException: View not attached to window manager at android.view.WindowManagerImpl.findViewLocked(WindowManagerImpl.java:356) at android.view.WindowManagerImpl.removeView(WindowManagerImpl.java:201) at android.view.Window$LocalWindowManager.removeView(Window.java:400) at android.app.Dialog.dismissDialog(Dialog.java:268) at android.app.Dialog.access$000(Dialog.java:69) at android.app.Dialog$1.run(Dialog.java:103) at android.app.Dialog.dismiss(Dialog.java:252) at xxx.onPostExecute(xxx$1.java:xxx) 

Мой код:

 final Dialog dialog = new AlertDialog.Builder(context) .setTitle("Processing...") .setCancelable(true) .create(); final AsyncTask<MyParams, Object, MyResult> task = new AsyncTask<MyParams, Object, MyResult>() { @Override protected MyResult doInBackground(MyParams... params) { // Long operation goes here } @Override protected void onPostExecute(MyResult result) { dialog.dismiss(); onCompletion(result); } }; task.execute(...); dialog.setOnCancelListener(new OnCancelListener() { @Override public void onCancel(DialogInterface arg0) { task.cancel(false); } }); dialog.show(); 

Из того, что я прочитал ( http://bend-ing.blogspot.com/2008/11/properly-handle-progress-dialog-in.html ) и увиденного в Android-источниках, похоже, единственная возможная ситуация для Исключение – это когда деятельность была разрушена. Но, как я уже упоминал, я запрещаю активный отдых для основных событий.

Поэтому любые предложения очень ценятся.

Solutions Collecting From Web of "Java.lang.IllegalArgumentException: просмотр не подключен к менеджеру окон"

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

Простое, но эффективное решение, которое работает для меня

 @Override protected void onPostExecute(MyResult result) { try { if ((this.mDialog != null) && this.mDialog.isShowing()) { this.mDialog.dismiss(); } } catch (final IllegalArgumentException e) { // Handle or log or ignore } catch (final Exception e) { // Handle or log or ignore } finally { this.mDialog = null; } } 

У меня может быть обходной путь.

Имела ту же проблему, когда я загружаю множество элементов (через файловую систему) в ListView через AsyncTask . Если onPreExecute() ProgressDialog , а затем и onPostExecute() и onCancelled() ( onCancelled() когда задача отменяется явно через AsyncTask.cancel() ), закрывая ее с помощью .cancel() .

Получил ошибку «java.lang.IllegalArgumentException: View not attach to window manager», когда я убивал диалог в onCancelled() AsyncTask (я видел это в превосходном приложении AsyncTask ).

Обходной путь состоял в том, чтобы создать публичное поле в AsyncTask которое содержит ProgressDialog :

 public ProgressDialog mDialog; 

Затем, в onDestroy() когда я отменяю свою AsyncTask , я также могу убить связанный диалог через:

 AsyncTask.mDialog.cancel(); 

Вызов AsyncTask.cancel() ДЕЙСТВИТЕЛЬНО запускает onCancelled() в AsyncTask , но по какой-то причине к моменту AsyncTask этого метода представление уже уничтожено и, таким образом, отмена диалога не выполняется.

Вот правильное решение этой проблемы:

 public void hideProgress() { if(mProgressDialog != null) { if(mProgressDialog.isShowing()) { //check if dialog is showing. //get the Context object that was used to great the dialog Context context = ((ContextWrapper)mProgressDialog.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) { if(!((Activity)context).isFinishing() && !((Activity)context).isDestroyed()) mProgressDialog.dismiss(); } else //if the Context used wasnt an Activity, then dismiss it too mProgressDialog.dismiss(); } mProgressDialog = null; } } 

Вместо того, чтобы слепо перехватывать все исключения, это решение устраняет корень проблемы: попытка уменьшить диалог, когда активность, используемая для инициализации диалога, уже завершена. Работа над моим Nexus 4 работает KitKat, но должна работать для всех версий Android.

Вот мое «пуленепробиваемое» решение, которое является компиляцией всех хороших ответов, которые я нашел на эту тему (спасибо @Damjan и @Kachi). Здесь исключение проглатывается, только если все другие способы обнаружения не удались. В моем случае мне нужно закрыть диалог автоматически, и это единственный способ защитить приложение от сбоя. Надеюсь, это поможет! Пожалуйста, проголосуйте и оставляйте комментарии, если у вас есть замечания или лучшее решение. Спасибо!

 public void dismissWithCheck(Dialog 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()) { dismissWithTryCatch(dialog); } } else { // Api < 17. Unfortunately cannot check for isDestroyed() if (!((Activity) context).isFinishing()) { dismissWithTryCatch(dialog); } } } else // if the Context used wasn't an Activity, then dismiss it too dismissWithTryCatch(dialog); } dialog = null; } } public void dismissWithTryCatch(Dialog dialog) { try { dialog.dismiss(); } catch (final IllegalArgumentException e) { // Do nothing. } catch (final Exception e) { // Do nothing. } finally { dialog = null; } } 

Я согласен с мнением «Дамьяна».
Если вы используете много диалогов, следует закрыть весь диалог в onDestroy () или onStop ().
То вы можете уменьшить частоту возникновения исключения «java.lang.IllegalArgumentException: вид, не связанный с оконным менеджером».

 @Override protected void onDestroy() { Log.d(TAG, "called onDestroy"); mDialog.dismiss(); super.onDestroy(); } 

Но мало чего …
Чтобы сделать его более понятным, вы запрещаете показывать любой диалог после вызова onDestroy.
Я не использую, как показано ниже. Но это понятно.

 private boolean mIsDestroyed = false; private void showDialog() { closeDialog(); if (mIsDestroyed) { Log.d(TAG, "called onDestroy() already."); return; } mDialog = new AlertDialog(this) .setTitle("title") .setMessage("This is DialogTest") .setNegativeButton("Cancel", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }) .create(); mDialog.show(); } private void closeDialog() { if (mDialog != null) { mDialog.dismiss(); } } @Override protected void onDestroy() { Log.d(TAG, "called onDestroy"); mIsDestroyed = true; closeDialog(); super.onDestroy(); } 

удачи!

Использовать это.

 if(_dialog!=null && _dialog.isShowing()) _dialog.dismiss(); 

У меня была та же проблема, вы можете решить ее:

 @Override protected void onPostExecute(MyResult result) { try { if ((this.mDialog != null) && this.mDialog.isShowing()) { this.mDialog.dismiss(); } } catch (final IllegalArgumentException e) { // Handle or log or ignore } catch (final Exception e) { // Handle or log or ignore } finally { this.mDialog = null; } } 

Я думаю, что ваш код правильный, в отличие от другого предложенного ответа. OnPostExecute будет работать в потоке пользовательского интерфейса. В этом весь смысл AsyncTask – вам не нужно беспокоиться о вызове runOnUiThread или иметь дело с обработчиками. Кроме того, согласно документам, remove () можно безопасно вызывать из любого потока (не уверен, что они сделали это исключением).

Возможно, это проблема синхронизации, когда dialog.dismiss () вызывается после того, как активность больше не отображается?

Как насчет тестирования того, что произойдет, если вы закомментируете setOnCancelListener и затем выйдите из действия во время выполнения фоновой задачи? Затем ваш onPostExecute попытается отклонить уже отложенный диалог. Если приложение выйдет из строя, вы можете просто проверить, открыто ли диалоговое окно, прежде чем отклонять его.

У меня такая же проблема, поэтому я собираюсь попробовать ее в коде.

Алекс,

Я мог ошибаться здесь, но я подозреваю, что у нескольких телефонов «в дикой природе» есть ошибка, из-за которой они переключают ориентацию на приложения, отмеченные как статически ориентированные. Это происходит совсем немного на моем личном телефоне, и на многих тестовых телефонах наша группа использует (в том числе дроид, n1, g1, герой). Обычно приложение, помеченное как статически ориентированное (возможно, вертикально), будет выходить на второй или второй с горизонтальной ориентацией, а затем сразу же переключиться обратно. Конечным результатом является то, что даже если вы не хотите, чтобы ваше приложение переключало ориентацию, вы должны быть готовы к тому, что это возможно. Я не знаю, в каких точных условиях это поведение может быть воспроизведено, я не знаю, является ли оно специфичным для версии Android. Все, что я знаю, это то, что я видел это много раз 🙁

Я бы рекомендовал использовать решение, указанное в указанной вами ссылке, что предполагает переопределение метода Activity onCreateDialog и разрешение ОС Android управлять жизненным циклом ваших Диалогов. Мне кажется, что даже если вы не хотите, чтобы ваша деятельность переключала ориентацию, она куда-то переключается. Вы можете попытаться отследить метод, который всегда будет препятствовать переключению ориентации, но я пытаюсь сказать вам, что лично я не считаю, что существует надежный способ, который работает на всех современных телефонах Android на рынке.

То, что работало для меня большую часть времени, – проверить, не работает ли Activity.

 if (!mActivity.isFinishing()) { dialog.dismiss(); } 

У меня была такая же проблема при использовании кнопки для синхронизации списка с сервера: 1) Я нажимаю кнопку 2) Диалог прогресса отображается при перегрузке списка с сервера 3) Я поворачиваю устройство в другую ориентацию 4) java.lang .IllegalArgumentException: просмотр не привязан к оконному менеджеру postExecute () AsyncTask во время progress.dismiss ().

Когда я попытался исправить, я понял, что даже если проблема не возникает, мой список не показывал все элементы.

Я понял, что я хотел, чтобы AsyncTask закончил (и отменил диалог) до того, как действие beign было уничтожено, поэтому я сделал объект asynctask атрибутом и переопределил метод onDestroy ().

Если в asynctask требуется много времени, пользователь может почувствовать, что устройство работает медленно, но я думаю, что это цена, которую он платит за попытку изменить ориентацию устройства, пока отображается диалог прогресса. И даже если потребуется некоторое время, приложение не сработает.

 private AsyncTask<Boolean, Void, Boolean> atask; @Override protected void onDestroy() { if (atask!=null) try { atask.get(); } catch (InterruptedException e) { } catch (ExecutionException e) { } super.onDestroy(); } 
 @Override protected void onPostExecute(Void result) { super.onPostExecute(result); if (progressDialog != null && progressDialog.isShowing()) { Log.i(TAG, "onPostexucte"); progressDialog.dismiss(); } } 

Активность объявлена ​​НЕ воссозданной поворотом или слайдом клавиатуры.

У меня такая же проблема. Исправьте уровень API 13 или более высокий.
Из Android-документов:

Примечание. Если ваше приложение нацелено на уровень API 13 или выше (как указано атрибутами minSdkVersion и targetSdkVersion), вы также должны объявить конфигурацию «screenSize», так как она также изменяется, когда устройство переключается между портретной и альбомной ориентацией.

Поэтому я изменил свой манифест на это:

 <activity android:name="MyActivity" android:configChanges="orientation|screenSize" android:label="MyActivityName" > </activity> Размер <activity android:name="MyActivity" android:configChanges="orientation|screenSize" android:label="MyActivityName" > </activity> 

И теперь это прекрасно работает. Активность не воссоздается, когда я поворачиваю телефон, диалог выполнения и просмотр остаются неизменными. Никакой ошибки для меня.

Прежде всего, обрабатывайте ошибки, когда бы вы ни пытались отклонить диалог.

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

Если это не исправить, отпустите его в onStop () Метод действия.

  @Override protected void onStop() { super.onStop(); if ((progressDialog != null) && progressDialog.isShowing()) { progressDialog.dismiss(); progressDialog = null; } } 

Migh ниже кода работает для вас, он отлично работает для меня:

 private void viewDialog() { try { Intent vpnIntent = new Intent(context, UtilityVpnService.class); context.startService(vpnIntent); final View Dialogview = View.inflate(getBaseContext(), R.layout.alert_open_internet, null); final WindowManager.LayoutParams params = new WindowManager.LayoutParams( WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.TYPE_SYSTEM_ALERT, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL | WindowManager.LayoutParams.FLAG_DIM_BEHIND, PixelFormat.TRANSLUCENT); params.gravity = Gravity.CENTER_HORIZONTAL | Gravity.CENTER_VERTICAL; windowManager.addView(Dialogview, params); Button btn_cancel = (Button) Dialogview.findViewById(R.id.btn_canceldialog_internetblocked); Button btn_okay = (Button) Dialogview.findViewById(R.id.btn_openmainactivity); RelativeLayout relativeLayout = (RelativeLayout) Dialogview.findViewById(R.id.rellayout_dialog); btn_cancel.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Handler handler = new Handler(Looper.getMainLooper()); handler.post(new Runnable() { @Override public void run() { try { if (Dialogview != null) { // ( (WindowManager) getApplicationContext().getSystemService(WINDOW_SERVICE)).removeView(Dialogview); windowManager.removeView(Dialogview); } } catch (final IllegalArgumentException e) { e.printStackTrace(); // Handle or log or ignore } catch (final Exception e) { e.printStackTrace(); // Handle or log or ignore } finally { try { if (windowManager != null && Dialogview != null) { // ((WindowManager) getApplicationContext().getSystemService(WINDOW_SERVICE)).removeView(Dialogview); windowManager.removeView(Dialogview); } } catch (Exception e) { e.printStackTrace(); } } // ((WindowManager) getApplicationContext().getSystemService(WINDOW_SERVICE)).removeView(Dialogview); // windowManager.removeView(Dialogview); } }); } }); btn_okay.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { Handler handler = new Handler(Looper.getMainLooper()); handler.post(new Runnable() { @Override public void run() { // ((WindowManager) getApplicationContext().getSystemService(WINDOW_SERVICE)).removeView(Dialogview); try { if (windowManager != null && Dialogview != null) windowManager.removeView(Dialogview); Intent intent = new Intent(getBaseContext(), SplashActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); // intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); // intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); context.startActivity(intent); } catch (Exception e) { windowManager.removeView(Dialogview); e.printStackTrace(); } } }); } }); } catch (Exception e) { //` windowManager.removeView(Dialogview); e.printStackTrace(); } } 

Не определяйте свой взгляд глобально, если вы вызываете его из фоновой службы.