100 votes

java.lang.IllegalStateException : L'enfant spécifié a déjà un parent

J'utilise des fragments, lorsque j'instancie un fragment la première fois, il le fait. Mais la deuxième fois, j'ai eu cette exception. Je n'ai pas pu trouver la ligne où j'ai eu l'erreur ?

 04-04 08:51:54.320: E/AndroidRuntime(29713): FATAL EXCEPTION: main
    04-04 08:51:54.320: E/AndroidRuntime(29713): java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
    04-04 08:51:54.320: E/AndroidRuntime(29713):    at android.view.ViewGroup.addViewInner(ViewGroup.java:3013)
    04-04 08:51:54.320: E/AndroidRuntime(29713):    at android.view.ViewGroup.addView(ViewGroup.java:2902)
    04-04 08:51:54.320: E/AndroidRuntime(29713):    at android.view.ViewGroup.addView(ViewGroup.java:2859)
    04-04 08:51:54.320: E/AndroidRuntime(29713):    at android.view.ViewGroup.addView(ViewGroup.java:2839)
    04-04 08:51:54.320: E/AndroidRuntime(29713):    at android.support.v4.app.NoSaveStateFrameLayout.wrap(Unknown Source)
    04-04 08:51:54.320: E/AndroidRuntime(29713):    at android.support.v4.app.FragmentManagerImpl.moveToState(Unknown Source)
    04-04 08:51:54.320: E/AndroidRuntime(29713):    at android.support.v4.app.FragmentManagerImpl.moveToState(Unknown Source)
    04-04 08:51:54.320: E/AndroidRuntime(29713):    at android.support.v4.app.BackStackRecord.run(Unknown Source)
    04-04 08:51:54.320: E/AndroidRuntime(29713):    at android.support.v4.app.FragmentManagerImpl.execPendingActions(Unknown Source)
    04-04 08:51:54.320: E/AndroidRuntime(29713):    at android.support.v4.app.FragmentManagerImpl$1.run(Unknown Source)
    04-04 08:51:54.320: E/AndroidRuntime(29713):    at android.os.Handler.handleCallback(Handler.java:587)
    04-04 08:51:54.320: E/AndroidRuntime(29713):    at android.os.Handler.dispatchMessage(Handler.java:92)
    04-04 08:51:54.320: E/AndroidRuntime(29713):    at android.os.Looper.loop(Looper.java:132)
    04-04 08:51:54.320: E/AndroidRuntime(29713):    at android.app.ActivityThread.main(ActivityThread.java:4126)
    04-04 08:51:54.320: E/AndroidRuntime(29713):    at java.lang.reflect.Method.invokeNative(Native Method)
    04-04 08:51:54.320: E/AndroidRuntime(29713):    at java.lang.reflect.Method.invoke(Method.java:491)
    04-04 08:51:54.320: E/AndroidRuntime(29713):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:844)
    04-04 08:51:54.320: E/AndroidRuntime(29713):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:602)
    04-04 08:51:54.320: E/AndroidRuntime(29713):    at dalvik.system.NativeStart.main(Native Method)

Voici ce que je fais lorsque je clique sur un élément de mon fragment de liste.

// If we are not currently showing a fragment for the new
 // position, we need to create and install a new one.
 RouteSearchFragment df = RouteSearchFragment.newInstance(index);

 // Execute a transaction, replacing any existing fragment
 // with this one inside the frame.
 FragmentTransaction ft = fragmentManager.beginTransaction();
 ft.replace(R.id.details_full, df);
 ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
 ft.commit();

La première fois, c'est OK, je clique sur l'élément 2 de la liste, c'est aussi OK ; mais quand je retourne à l'élément 1, j'ai ce bug.

Merci à tous !

0 votes

Il faut appeler layoutView.removeAllViews() ; avant d'ajouter des vues au layout.

0 votes

@imrankhan faux ! Vous pouvez ajouter sans tout enlever. La partie la plus importante est manquante et comme il n'y a pas de paquet personnalisé dans le stacktrace, je vous suggère de supprimer du code et de le tester étape par étape...

1 votes

J'ai ajouté plus de détails, s'il vous plaît pouvez-vous voir cela ?

371voto

Patrick Points 2386

Désolé de répondre à une vieille question, mais j'ai réussi à résoudre le problème en utilisant une solution totalement différente. J'obtenais cette exception mais j'ai changé la première ligne de ma commande onCreatView de la façon suivante :

View result = inflater.inflate(R.layout.customer_layout, container);

...à ceci :

View result = inflater.inflate(R.layout.customer_layout, container, false);

Je ne sais pas pourquoi, mais l'utilisation de la dérogation qui accepte le booléen comme troisième paramètre a réglé le problème. Je pense que cela indique au fragment et/ou à l'activité de ne pas utiliser le "conteneur" comme parent de la vue nouvellement créée.

53 votes

Ne soyez pas désolés - cela m'a été très utile, ainsi qu'à un certain nombre d'autres personnes. Merci !

0 votes

Merci beaucoup, j'oublie toujours ce point et je reviens à cette réponse.

0 votes

@Patrick, La première attache la vue gonflée au conteneur, l'ajout du false flag spécifie que vous ne voulez pas ajouter la vue gonflée au conteneur.

45voto

Hardik Points 236

J'ai rencontré ce problème à plusieurs reprises. Veuillez ajouter le code suivant pour résoudre ce problème :

@Override
    public void onDestroyView() {
        super.onDestroyView();
        if (view != null) {
            ViewGroup parentViewGroup = (ViewGroup) view.getParent();
            if (parentViewGroup != null) {
                parentViewGroup.removeAllViews();
            }
        }
    }

Gracias

0 votes

Merci pour cette solution :) J'ai un cas très spécifique où je ne peux pas utiliser l'inflateur pour résoudre ce problème. Vous m'avez fait gagner beaucoup de temps

0 votes

Je suis désolé, je ne comprends pas bien parce que je suis nouveau sur Android.

0 votes

En view.getParent() ; D'où vient l'objet view ?

36voto

Medo Points 363

Lorsque vous passez outre OnCreateView dans votre RouteSearchFragment vous avez le

if(view != null) {
    return view; 
}

segment de code ?

Si c'est le cas, la suppression de la déclaration de retour devrait résoudre votre problème.

Vous pouvez conserver le code et renvoyer la vue si vous ne voulez pas régénérer les données de la vue, et la méthode onDestroyView() permet de supprimer cette vue de son parent comme suit :

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        if (view != null) {
            ViewGroup parent = (ViewGroup) view.getParent();
            if (parent != null) {
                parent.removeAllViews();
            }
        }
    }

5 votes

@Override public void onDestroyView() { super.onDestroyView() ; ViewGroup parentViewGroup = (ViewGroup) mRoutesSearchViewContainer.getParent() ; if( null != parentViewGroup ) { parentViewGroup.removeView( mRoutesSearchViewContainer ) ; } }. }

0 votes

@Medo : Pouvez-vous donner une brève explication à ce sujet. J'ai la même erreur affichée dans le logcat. Comme vous l'avez suggéré "supprimer la déclaration de retour devrait résoudre votre problème", mais nous avons besoin de retourner l'objet View dans la méthode onCreateView(). pouvez-vous fournir un extrait de code pour votre explication. Je vous remercie.

0 votes

@Krishna Gonflez et renvoyez la vue comme vous le feriez normalement. Vous pouvez sauter l'ensemble de l'instruction if.

35voto

Dhananjay Points 21

Si vous avez cette déclaration..

View view = inflater.inflate(R.layout.fragment1, container);//may be Incorrect 

Alors essayez ceci Ajoutez false comme troisième argument Peut-être que ça pourrait aider

View view = inflater.inflate(R.layout.fragment1, container, false);//correct one

22voto

user1736525 Points 253

J'avais ce code dans un fragment et il plantait si j'essayais de revenir à ce fragment.

if (mRootView == null) {
    mRootView = inflater.inflate(R.layout.fragment_main, container, false);
} 

Après avoir rassemblé les réponses sur ce fil, j'ai réalisé que le parent de mRootView a toujours mRootView comme enfant. C'était donc ma solution.

if (mRootView == null) {
    mRootView = inflater.inflate(R.layout.fragment_main, container, false);
} else {
    ((ViewGroup) mRootView.getParent()).removeView(mRootView);
}

J'espère que cela vous aidera

2 votes

+1 m'a aidé. C'est particulièrement vrai si votre activité reste mais que le gestionnaire de fragments ajoute de nouveaux fragments par-dessus. Quand il revient au premier fragment, il faut s'assurer que l'ancienne vue racine est supprimée. Merci !

0 votes

Cela m'a beaucoup aidé. J'ai cherché cette solution pendant 3 jours. Une réponse simple et jolie.

0 votes

Wow ! enfin ça a marché pour moi ! solution grat. merci !

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