115 votes

Vue Android non attachée au gestionnaire de fenêtres

Je rencontre les exceptions suivantes :

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)

J'ai fait une recherche sur Google et j'ai vu que cela avait quelque chose à voir avec les fenêtres pop-up et la rotation de l'écran, mais il n'y a aucune référence à mon code.

Les questions sont les suivantes :

  1. Y a-t-il un moyen de savoir exactement quand ce problème se produit ?
  2. À part tourner l'écran, y a-t-il un autre événement ou une autre action qui déclenche cette erreur ?
  3. comment éviter que cela ne se produise ?

1 votes

Voyez si vous pouvez expliquer comment l'activité est décrite dans le manifeste et quelle activité s'affiche à l'écran lorsque l'erreur se produit. Voyez si vous pouvez réduire votre problème à un testcase minimal.

0 votes

Peut-être essayez-vous de modifier votre vue avant View#onAttachedToWindow() a été appelé ?

163voto

johnnyblizzard Points 546

J'avais ce problème où, lors d'un changement d'orientation de l'écran, l'activité se terminait avant l'AsyncTask avec le dialogue de progression. J'ai semblé résoudre ce problème en donnant la valeur null à la boîte de dialogue. onPause() puis de le vérifier dans l'AsyncTask avant de le rejeter.

@Override
public void onPause() {
    super.onPause();

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

... dans mon AsyncTask :

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

protected void onPostExecute(Object result) {
   if ((mDialog != null) && mDialog.isShowing()) { 
        mDialog.dismiss();
   }
}

13 votes

@YekhezkelYovel l'AsyncTask s'exécute dans un thread qui survit au redémarrage de l'activité et peut contenir des références à l'activité morte et à ses vues (il s'agit effectivement d'une fuite de mémoire, bien que probablement à court terme - cela dépend du temps que prend la tâche pour se terminer). La solution ci-dessus fonctionne bien, si vous êtes prêt à accepter une fuite de mémoire à court terme. L'approche recommandée consiste à annuler() toute tâche asynchrone en cours d'exécution lorsque l'activité est mise en pause.

0voto

rickey Points 1822

J'ai ajouté ce qui suit au manifeste pour cette activité

android:configChanges="keyboardHidden|orientation|screenLayout"

19 votes

Ce n'est pas une solution : Le système pourrait détruire votre activité pour d'autres raisons également.

1 votes

Pouvez-vous expliquer votre réponse ?

0voto

Steve Haley Points 26928

Pour la question 1) :

Étant donné que le message d'erreur ne semble pas indiquer quelle ligne de votre code est à l'origine du problème, vous pouvez le localiser en utilisant des points d'arrêt. Les points d'arrêt interrompent l'exécution du programme lorsqu'il atteint des lignes de code spécifiques. En ajoutant des points d'arrêt à des endroits critiques, vous pouvez déterminer quelle ligne de code est à l'origine du plantage. Par exemple, si votre programme se bloque à la ligne setContentView(), vous pouvez placer un point d'arrêt à cet endroit. Lorsque le programme s'exécute, il se met en pause avant d'exécuter cette ligne. Si, en reprenant l'exécution, le programme se plante avant d'atteindre le point d'arrêt suivant, vous savez alors que la ligne qui a tué le programme se trouvait entre les deux points d'arrêt.

L'ajout de points d'arrêt est facile si vous utilisez Eclipse. Faites un clic droit dans la marge juste à gauche de votre code et sélectionnez "Toggle breakpoint". Vous devez ensuite exécuter votre application en mode débogage, le bouton qui ressemble à un insecte vert à côté du bouton d'exécution normal. Lorsque le programme atteint un point d'arrêt, Eclipse bascule dans la perspective de débogage et vous montre la ligne sur laquelle il est en attente. Pour relancer l'exécution du programme, recherchez le bouton "Resume", qui ressemble à un bouton "Play" normal, mais avec une barre verticale à gauche du triangle.

Vous pouvez également remplir votre application avec Log.d("My application", "Some information here that tells you where the log line is"), qui affiche alors les messages dans la fenêtre LogCat d'Eclipse. Si vous ne trouvez pas cette fenêtre, ouvrez-la avec Fenêtre -> Afficher la vue -> Autre... -> Android -> LogCat.

J'espère que cela vous aidera !

7 votes

Le problème se produit sur les téléphones des clients, je n'ai donc pas la possibilité de déboguer. De plus, le problème se produit tout le temps, mais seulement de temps en temps, donc je ne sais pas comment le suivre.

0 votes

Vous pouvez toujours obtenir des messages de débogage à partir d'un téléphone, si vous pouvez mettre la main dessus. Dans le menu -> paramètres -> applications -> développement, il y a une option pour le débogage USB. Si cette option est activée, vous pouvez alors brancher le téléphone et LogCat récupère toutes les lignes de débogage normales. A part ça... et bien... l'intermittence pourrait s'expliquer par le fait qu'elle dépend de l'état du programme. Je suppose que vous devriez essayer d'utiliser le programme pour voir si vous pouvez recréer le problème.

4 votes

Comme je l'ai déjà dit, le problème se produit sur le téléphone d'un client, et je n'y ai pas accès. Le client est peut-être sur un autre continent :)

0voto

Sarith Vasu Points 43

Ou simplement vous pouvez ajouter

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

ce qui rendra le ProgressDialog à non annulable

0voto

android developer Points 20939

Selon le code du windowManager (lien aquí ), cela se produit lorsque la vue que vous essayez de mettre à jour (qui appartient probablement à un dialogue, mais ce n'est pas nécessaire) n'est plus attachée à la racine réelle de la fenêtre.

comme d'autres l'ont suggéré, vous devriez vérifier le statut de l'activité avant d'effectuer des opérations spéciales sur vos boîtes de dialogue.

Voici le code pertinent, qui est la cause du problème (copié du code source d'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;
        }
    }

0 votes

Le code que j'ai écrit ici est ce que google fait. ce que j'ai écrit est dans le but de montrer la cause de ce problème.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X