J'ai une activité qui démarre AsyncTask et affiche une boîte de dialogue de progression pour la durée de l'opération. L'activité est déclarée ne pas être recréée par rotation ou par glissement du clavier.
<activity android:name=".MyActivity"
android:label="@string/app_name"
android:configChanges="keyboardHidden|orientation"
>
<intent-filter>
</intent-filter>
</activity>
Une fois la tâche terminée, je dissipe le dialogue, mais sur certains téléphones (framework: 1.5, 1.6), une telle erreur est générée:
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)
Mon code est:
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();
D'après ce que j'ai lu ( http://bend-ing.blogspot.com/2008/11/properly-handle-progress-dialog-in.html ) et vu dans les sources Android, il semble que la seule situation possible pour l'obtenir l'exception est lorsque l'activité a été détruite. Mais comme je l'ai mentionné, j'interdis les activités récréatives pour les événements de base.
Donc, toutes les suggestions sont très appréciées.
Réponses:
Moi aussi , je reçois cette erreur parfois quand je rejette le dialogue et l' activité de finition de méthode onPostExecute. Je suppose que parfois l'activité se termine avant que le dialogue ne se termine avec succès.
Solution simple mais efficace qui fonctionne pour moi
la source
Voici ma solution "bullet proof", qui est la compilation de toutes les bonnes réponses que j'ai trouvées sur ce sujet (merci à @Damjan et @Kachi). Ici, l'exception n'est acceptée que si toutes les autres méthodes de détection n'ont pas réussi. Dans mon cas, je dois fermer la boîte de dialogue automatiquement et c'est le seul moyen de protéger l'application contre les plantages. J'espère que cela vous aidera! S'il vous plaît, votez et laissez des commentaires si vous avez des remarques ou une meilleure solution. Je vous remercie!
la source
dialog = null
n'a aucun effet. EtStatusEventDialog
devrait lire justeDialog
.isDestroyed()
n'est pas disponible, mais pour des raisons pratiques, ne serait-il pas toujours la même chose d'utiliser le try / catch?J'ai peut-être une solution de contournement.
Avait le même problème, où je charge beaucoup d'éléments (via le système de fichiers) dans un
ListView
via un fichierAsyncTask
. Avait leonPreExecute()
déclenchement d'unProgressDialog
, puis les deuxonPostExecute()
etonCancelled()
(appelé lorsque la tâche est annulée explicitement viaAsyncTask.cancel()
) en le fermant via.cancel()
.J'ai eu la même erreur "java.lang.IllegalArgumentException: View not attach to window manager" lorsque je tuais la boîte de dialogue dans la
onCancelled()
méthode duAsyncTask
(j'avais vu cela fait dans l'excellente application Shelves ).La solution de contournement consistait à créer un champ public dans le
AsyncTask
qui contient leProgressDialog
:Ensuite,
onDestroy()
lorsque j'annule monAsyncTask
, je peux également supprimer la boîte de dialogue associée via:L'appel du
AsyncTask.cancel()
déclencheur DOESonCancelled()
dans leAsyncTask
, mais pour une raison quelconque au moment où cette méthode est appelée, la vue a déjà été détruite et l'annulation de la boîte de dialogue échoue.la source
Voici la bonne solution pour résoudre ce problème:
Au lieu d'attraper aveuglément toutes les exceptions, cette solution s'attaque à la racine du problème: essayer de masquer une boîte de dialogue lorsque l'activité utilisée pour initialiser la boîte de dialogue est déjà terminée. Travaille sur mon Nexus 4 exécutant KitKat, mais devrait fonctionner pour toutes les versions d'Android.
la source
isDestroyed
nécessite l'API 17+Je suis d'accord avec une opinion de «Damjan».
si vous utilisez de nombreuses boîtes de dialogue, vous devez fermer toutes les boîtes de dialogue dans onDestroy () ou onStop ().
alors vous pourrez peut-être réduire la fréquence d'exception «java.lang.IllegalArgumentException: Vue non attachée au gestionnaire de fenêtres».
mais peu de dépassement ...
pour que ce soit plus clair, vous évitez d'afficher une boîte de dialogue après l'appel de onDestroy.
je n'utilise pas comme ci-dessous. mais c'est clair.
bonne chance!
la source
Utilisez ceci.
la source
if
dans des cas comme celui-ci, l'&&
opérateur de Java a une évaluation paresseuse (également appelée court-circuit), ce qui signifie que le 2ème opérande n'est pas évalué si le premier est évalué àfalse
(ce qui signifie le résultat de le&&
sera toujours defalse
toute façon, d'où l'évaluation "paresseuse"). De même||
n'évaluera pas son 2e opérande si le premier est évalué àtrue
. Remarque: les opérateurs&
et|
n'ont pas ce comportement et évaluent donc toujours les deux opérandes.J'ai eu le même problème, vous pouvez le résoudre en:
la source
Je pense que votre code est correct contrairement à l'autre réponse suggérée. onPostExecute s'exécutera sur le thread d'interface utilisateur. C'est tout l'intérêt d'AsyncTask - vous n'avez pas à vous soucier d'appeler runOnUiThread ou de gérer les gestionnaires. De plus, selon la documentation, ignore () peut être appelé en toute sécurité à partir de n'importe quel thread (pas sûr qu'ils en aient fait l'exception).
C'est peut-être un problème de synchronisation où dialog.dismiss () est appelé après que l'activité ne soit plus affichée?
Qu'en est-il du test de ce qui se passe si vous commentez le setOnCancelListener puis quittez l'activité pendant que la tâche d'arrière-plan est en cours d'exécution? Ensuite, votre onPostExecute essaiera de fermer une boîte de dialogue déjà fermée. Si l'application plante, vous pouvez probablement simplement vérifier si la boîte de dialogue est ouverte avant de la fermer.
J'ai exactement le même problème, donc je vais l'essayer dans le code.
la source
Alex,
Je peux me tromper ici, mais je soupçonne que plusieurs téléphones «dans la nature» ont un bogue qui les amène à changer d'orientation sur les applications marquées comme orientées statiquement. Cela se produit un peu sur mon téléphone personnel et sur de nombreux téléphones de test que notre groupe utilise (y compris droid, n1, g1, hero). En règle générale, une application marquée comme étant orientée statiquement (peut-être verticalement) se déploie pendant une seconde ou deux en utilisant une orientation horizontale, puis revient immédiatement en arrière. Le résultat final est que même si vous ne voulez pas que votre application change d'orientation, vous devez être prêt à le faire. Je ne sais pas dans quelles conditions exactes ce comportement peut être reproduit, je ne sais pas s'il est spécifique à une version d'Android. Tout ce que je sais, c'est que je l'ai vu arriver de nombreuses fois :(
Je recommanderais d'utiliser la solution fournie dans le lien que vous avez publié qui suggère de remplacer la méthode Activity onCreateDialog et de laisser le système d'exploitation Android gérer le cycle de vie de vos dialogues. Il me semble que même si vous ne voulez pas que votre activité change d'orientation, elle change d'orientation quelque part. Vous pouvez essayer de trouver une méthode qui empêchera toujours le changement d'orientation, mais j'essaie de vous dire que personnellement, je ne pense pas qu'il existe un moyen infaillible qui fonctionne sur tous les téléphones Android actuels sur le marché.
la source
Ce qui a fonctionné pour moi la plupart du temps, c'est de vérifier si l'activité ne se termine pas.
la source
J'ai juste le même problème. Correction pour le niveau d'API 13 ou higer.
À partir de la documentation Android:
J'ai donc changé mon manifeste en ceci:
Et maintenant, cela fonctionne très bien. L'activité ne se recrée pas lorsque je fais pivoter le téléphone, la boîte de dialogue de progression et la vue restent les mêmes. Aucune erreur pour moi.
la source
Tout d'abord, effectuez la gestion des erreurs là où vous essayez de fermer la boîte de dialogue.
Si cela ne résout pas le problème, ignorez-le dans la méthode onStop () de l'activité.
la source
J'ai eu le même problème en utilisant un bouton pour synchroniser une liste à partir du serveur: 1) Je clique sur le bouton 2) Une boîte de dialogue de progression apparaît lors du téléchargement de la liste à partir du serveur 3) Je tourne l'appareil vers une autre orientation 4) java.lang .IllegalArgumentException: Vue non attachée au gestionnaire de fenêtres sur postExecute () de la AsyncTask pendant progress.dismiss ().
En essayant le correctif, j'ai pensé que même si le problème ne se produisait pas, ma liste n'affichait pas tous les éléments.
J'ai pensé que ce que je voulais, c'était que AsyncTask se termine (et ferme la boîte de dialogue) avant que l'activité ne soit détruite, j'ai donc fait de l'objet asynctask un attribut et remplacé la méthode onDestroy ().
Si l'asynctask prend beaucoup de temps, l'utilisateur aura peut-être l'impression que l'appareil est lent, mais je pense que c'est le prix qu'il paie pour essayer de changer l'orientation de l'appareil pendant que la boîte de dialogue de progression s'affiche. Et même si cela prend du temps, l'application ne plante pas.
la source
la source
Le code ci-dessous fonctionne pour vous, cela fonctionne parfaitement pour moi:
Ne définissez pas votre vue globalement si vous l'appelez à partir du service d'arrière-plan.
la source