У меня есть действие, которое запускает 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, похоже, что единственно возможная ситуация, чтобы это получить Исключение составляют случаи, когда деятельность была уничтожена. Но, как я уже упоминал, я запрещаю активный отдых для основных событий.
Так что любые предложения очень ценятся.
Ответы:
Я тоже иногда получаю эту ошибку когда закрываю диалог и завершаю действие из метода onPostExecute. Я предполагаю, что иногда деятельность завершается до успешного закрытия диалога.
Простое, но эффективное решение, которое работает для меня
источник
Вот мое «пуленепробиваемое» решение, которое представляет собой сборник всех хороших ответов, которые я нашел по этой теме (благодаря @Damjan и @Kachi). Здесь исключение проглатывается, только если все другие способы обнаружения не увенчались успехом. В моем случае мне нужно закрыть диалоговое окно автоматически, и это единственный способ защитить приложение от сбоев. Я надеюсь, что это поможет вам! Пожалуйста, голосуйте и оставляйте комментарии, если у вас есть замечания или лучшее решение. Спасибо!
источник
dialog = null
не имеет никакого эффекта. ИStatusEventDialog
должен читать как разDialog
.isDestroyed()
он недоступен, но для практических целей не будет ли просто использовать try / catch всегда?У меня может быть обходной путь.
У меня возникла та же проблема, когда я загружал много элементов (через файловую систему) в
ListView
черезAsyncTask
. ЗапустилonPreExecute()
aProgressDialog
, а затем обаonPostExecute()
иonCancelled()
(вызывали, когда задача была явно отменена черезAsyncTask.cancel()
), закрывая его через.cancel()
.Получила ту же ошибку "java.lang.IllegalArgumentException: представление не привязано к диспетчеру окон", когда я убивал диалоговое окно в
onCancelled()
методеAsyncTask
(я видел это в отличном приложении Shelves ).Обходной путь должен был создать публичное поле в,
AsyncTask
которое содержитProgressDialog
:Затем,
onDestroy()
когда я отменяю свойAsyncTask
, я также могу убить связанный диалог через:Вызов
AsyncTask.cancel()
DOES срабатываетonCancelled()
вAsyncTask
, но по какой-то причине к тому времени, когда этот метод вызывается, представление уже уничтожено, и, таким образом, отмена диалога завершается неудачно.источник
Вот правильное решение этой проблемы:
Вместо того, чтобы слепо перехватывать все исключения, это решение обращается к корню проблемы: пытается закрыть диалоговое окно, когда действие, использованное для инициализации диалога, уже завершено. Работаю на моем Nexus 4 под управлением KitKat, но должен работать на всех версиях Android.
источник
isDestroyed
требуется API 17+Я согласен с мнением «Дамжана».
если вы используете много диалогов, следует закрыть все диалоги в onDestroy () или onStop ().
тогда вы сможете уменьшить частоту возникновения исключения «java.lang.IllegalArgumentException: представление, не привязанное к оконному менеджеру».
но немного превосходит ...
чтобы было понятнее, вы не можете показывать диалог после вызова onDestroy.
я не использую, как показано ниже. но это понятно.
удачи!
источник
Использовать это.
источник
if
,&&
оператор Java имеет ленивую оценку (также называемую коротким замыканием), что означает, что 2-й операнд не вычисляется, если первый операнд оцениваетсяfalse
(что означает результат&&
всегда будет вfalse
любом случае, следовательно , «ленивые» оценка). Аналогичным образом||
не будет оцениваться его второй операнд, если первый оцениваетtrue
. Примечание:&
и|
операторы не имеют такого поведения и , таким образом , всегда оценивать оба операнда.У меня была такая же проблема, вы можете решить ее:
источник
Я думаю, что ваш код правильный, в отличие от другого ответа. onPostExecute будет работать в потоке пользовательского интерфейса. В этом весь смысл AsyncTask - вам не нужно беспокоиться о вызове runOnUiThread или о обработчиках. Кроме того, согласно документации, dismiss () может быть безопасно вызван из любого потока (не уверен, что они сделали это исключением).
Возможно, это проблема синхронизации, когда dialog.dismiss () вызывается после того, как активность больше не отображается?
Как насчет тестирования, что произойдет, если вы закомментируете setOnCancelListener, а затем выйдете из действия во время выполнения фоновой задачи? Затем ваш onPostExecute попытается закрыть уже закрытое диалоговое окно. Если приложение падает, вы можете просто проверить, открыто ли диалоговое окно, прежде чем закрыть его.
У меня точно такая же проблема, поэтому я собираюсь попробовать это в коде.
источник
Алекс,
Я могу ошибаться, но я подозреваю, что у нескольких телефонов «в дикой природе» есть ошибка, которая заставляет их переключать ориентацию в приложениях, помеченных как статически ориентированные. Это происходит довольно часто на моем личном телефоне и на многих тестовых телефонах, которые использует наша группа (включая droid, n1, g1, hero). Обычно приложение, помеченное как статически ориентированное (возможно, вертикально), выкладывается на секунду или две, используя горизонтальную ориентацию, а затем немедленно переключается обратно. Конечным результатом является то, что даже если вы не хотите, чтобы ваше приложение меняло ориентацию, вы должны быть готовы к этому. Я не знаю, при каких условиях это поведение может быть воспроизведено, я не знаю, относится ли оно к какой-либо версии Android. Все, что я знаю, это то, что я видел это много раз :(
Я бы порекомендовал использовать решение, представленное в опубликованной вами ссылке, которое предлагает переопределить метод Activity onCreateDialog и позволить ОС Android управлять жизненным циклом ваших диалогов. Мне кажется, что даже если вы не хотите, чтобы ваша деятельность меняла ориентацию, она куда-то меняет ориентацию. Вы можете попытаться отследить метод, который всегда будет препятствовать переключению ориентации, но я пытаюсь сказать вам, что лично я не верю, что есть надежный способ, который работает на всех современных телефонах Android на рынке.
источник
То, что для меня работало большую часть времени, это проверить, не заканчивается ли действие.
источник
Просто получил ту же проблему. Исправлено для уровня API 13 или выше.
Из документов Android:
Итак, я изменил свой манифест на это:
И теперь работает нормально. Активность не воссоздается, когда я поворачиваю телефон, диалоговое окно прогресса и вид остаются прежними. Нет ошибки для меня.
источник
Прежде всего, делайте обработку ошибок там, где вы пытаетесь закрыть диалог.
Если это не помогло, тогда отклоните его в методе действия onStop ().
источник
У меня была такая же проблема при использовании кнопки для синхронизации списка с сервера: 1) я нажимаю кнопку 2) появляется диалоговое окно прогресса при загрузке списка с сервера 3) я переключаю устройство в другую ориентацию 4) java.lang .IllegalArgumentException: представление не присоединено к оконному менеджеру в postExecute () AsyncTask во время progress.dismiss ().
Когда я попытался исправить это, я понял, что даже если проблема не возникает, в моем списке отображаются не все элементы.
Я решил, что AsyncTask должен завершить (и закрыть диалоговое окно) до уничтожения beign действия, поэтому я сделал объект asynctask атрибутом и переопределил метод onDestroy ().
Если асинхронная задача занимает много времени, пользователь, возможно, почувствует, что устройство работает медленно, но я думаю, что он платит за попытку изменить ориентацию устройства, пока отображается диалоговое окно прогресса. И даже если это занимает некоторое время, приложение не падает.
источник
источник
Может ниже код работает для вас, он работает для меня прекрасно:
Не определяйте свое представление глобально, если вы вызываете его из фоновой службы.
источник