java.lang.IllegalStateException: Das angegebene Kind hat bereits ein Elternteil

99

Ich verwende Fragmente, wenn ich ein Fragment beim ersten Mal instanziiere. aber das zweite mal habe ich diese ausnahme bekommen. Ich konnte die Zeile nicht finden, in der ich den Fehler erhalten habe.

 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)

Folgendes mache ich, wenn ich auf ein Element meines Listenfragments klicke.

// 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();

Wenn es zum ersten Mal in Ordnung ist, klicke ich in der Liste auf element2. Es ist auch in Ordnung. Aber wenn ich zu Element1 zurückkehre, habe ich diesen Fehler.

Vielen Dank an alle!

haythem souissi
quelle
muss layoutView.removeAllViews () aufrufen; bevor Sie Ansichten zum Layout hinzufügen
ρяσsρєя K
@imrankhan falsch! Sie können hinzufügen, ohne alle zu entfernen. Der wichtigste Teil fehlt und da es kein benutzerdefiniertes Paket im Stacktrace gibt, empfehle ich Ihnen, Code zu entfernen und ihn Schritt für Schritt zu testen ...
WarrenFaith
1
Ich füge weitere Details hinzu. Kannst du das bitte sehen?
Haythem Souissi
Was ist diese RouteSearchFragment-Klasse? In Android-Dokumenten kann keine Referenz gefunden werden. Bitte aktualisieren Sie auch die Klassendefinition.
Noob

Antworten:

36

Wenn Sie OnCreateViewin Ihrer RouteSearchFragmentKlasse überschreiben , haben Sie die

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

Codesegment?

Wenn ja, sollte das Entfernen der return-Anweisung Ihr Problem lösen.

Sie können den Code beibehalten und die Ansicht zurückgeben, wenn Sie die Ansichtsdaten nicht neu generieren möchten. Mit der onDestroyView () -Methode entfernen Sie diese Ansicht wie folgt aus dem übergeordneten Element:

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        if (view != null) {
            ViewGroup parent = (ViewGroup) view.getParent();
            if (parent != null) {
                parent.removeAllViews();
            }
        }
    }
Medo
quelle
5
@Override public void onDestroyView () {super.onDestroyView (); ViewGroup parentViewGroup = (ViewGroup) mRoutesSearchViewContainer.getParent (); if (null! = parentViewGroup) {parentViewGroup.removeView (mRoutesSearchViewContainer); }}
Haythem Souissi
@Medo: Kannst du das kurz erklären? Ich habe den gleichen Fehler in der Logcat angezeigt. Da Sie den Vorschlag "Entfernen der return-Anweisung sollte Ihr Problem lösen" gegeben haben, müssen wir das View-Objekt in der onCreateView () -Methode zurückgeben. Können Sie Snippet-Code für Ihre Erklärung bereitstellen? Danke dir.
Krishna Prasad
@Krishna Einfach aufblasen und die Ansicht wie gewohnt zurückgeben. Sie können die gesamte if-Anweisung überspringen.
Medo
65
Für mich, ich musste einfach ersetzen return inflater.inflate(R.layout.fragment_search, container);mitreturn inflater.inflate(R.layout.fragment_search, container, false);
Sufian
370

Es tut mir leid, auf eine alte Frage zu posten, aber ich konnte sie mit einer völlig anderen Lösung beheben. Ich habe diese Ausnahme erhalten, aber die erste Zeile meiner onCreatView-Überschreibung wurde geändert:

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

... dazu:

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

Ich habe keine Ahnung warum, aber die Verwendung der Überschreibung, die den Booleschen Wert als dritten Parameter akzeptiert, hat ihn behoben. Ich denke, es weist das Fragment und / oder die Aktivität an, den "Container" nicht als übergeordnetes Element der neu erstellten Ansicht zu verwenden.

Patrick
quelle
53
Tut mir nicht leid - das war sehr nützlich für mich und eindeutig für eine Reihe anderer Leute. Vielen Dank!
Kopf in den Codes
Vielen Dank, ich vergesse dies immer wieder und komme auf diese Antwort zurück
Noloman
@Patrick, Der erste hängt die aufgeblasene Ansicht an den Container an. Durch Hinzufügen des falschen Flags wird angegeben, dass Sie die aufgeblasene Ansicht nicht zum Container hinzufügen möchten.
Ne0
und ich komme immer wieder auf diesen Beitrag zurück und
finde
45

Ich habe dieses Problem viele Male konfrontiert. Bitte fügen Sie folgenden Code hinzu, um dieses Problem zu beheben:

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

Vielen Dank

Hardik
quelle
Vielen Dank für diese Lösung :) Ich habe einen sehr speziellen Fall, in dem ich Inflater nicht verwenden kann, um dies zu lösen. Du hast mir viel Zeit gespart
Bojan
Es tut mir leid, ich verstehe nicht ganz, weil ich neu in Android bin.
Zin Win Htet
In view.getParent (); Woher kommt das Dosisansichtsobjekt?
Zin Win Htet
Cristy YG: Nehmen Sie eine View-Instanz als globale Variable und füllen Sie Ihre Layout-XML auf die oben genannte globale Variable. folgst du mir oder nicht?
Hardik
Ja, Instanz anzeigen als global deklarieren.
Hardik
35

Wenn Sie diese Aussage haben ..

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

Dann versuchen Sie dies. Fügen Sie als drittes Argument false hinzu. Vielleicht könnte es helfen.

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

Ich hatte diesen Code in einem Fragment und er stürzte ab, wenn ich versuchte, zu diesem Fragment zurückzukehren

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

Nachdem ich die Antworten in diesem Thread gesammelt hatte, stellte ich fest, dass die Eltern von mRootView immer noch mRootView als Kind haben. Das war also mein Fix.

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

hoffe das hilft

user1736525
quelle
2
+1 hat mir geholfen. Dies gilt insbesondere dann, wenn Ihre Aktivität erhalten bleibt, der Fragmentmanager jedoch neue Fragmente hinzufügt. Wenn es zum ersten Fragment zurückkehrt, müssen Sie sicherstellen, dass die alte Stammansicht entfernt wird. Vielen Dank!
Bundeeteddee
Es hat mir sehr geholfen. Ich habe diese Lösung seit 3 ​​Tagen gefunden. Einfache und hübsche Antwort.
Zin Win Htet
Beeindruckend! endlich hat es bei mir geklappt! gute Lösung. Vielen Dank!
Avisper
Ich habe keine Begründung, warum "(ViewGroup) mRootView.getParent ()). RemoveView (mRootView);" funktioniert im Gegensatz zum direkten Aufrufen von "<WhateverIsParentViewGroupName> .removeView (mRootView)". Aber das funktioniert auch für mich, ich teste auf Android 8.0 und 9.0. Danke Kumpel ^
Khay
16

Dies passiert auch, wenn die von onCreateView () zurückgegebene Ansicht nicht die Ansicht ist, die aufgeblasen wurde.

Beispiel:

View rootView = inflater.inflate(R.layout.my_fragment, container, false);

TextView textView = (TextView) rootView.findViewById(R.id.text_view);
textView.setText("Some text.");

return textView;

Fix:

return rootView;

Anstatt:

return textView; // or whatever you returned
Mateus Pires
quelle
Vielen Dank! Es hat mir geholfen!
Sudheesh Mohan
5

Ich hatte dieses Problem und konnte es nicht in Java-Code lösen. Das Problem war mit meiner XML.

Ich habe versucht, einem Container eine Textansicht hinzuzufügen, aber die Textansicht in ein LinearLayout eingeschlossen.

Dies war die ursprüngliche XML-Datei:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    
    <TextView xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@android:id/text1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceListItemSmall"
        android:gravity="center_vertical"
        android:paddingLeft="16dp"
        android:paddingRight="16dp"
        android:textColor="#fff"
        android:background="?android:attr/activatedBackgroundIndicator"
        android:minHeight="?android:attr/listPreferredItemHeightSmall"/>

</LinearLayout>

Jetzt mit entferntem LinearLayout:

<TextView xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@android:id/text1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceListItemSmall"
        android:gravity="center_vertical"
        android:paddingLeft="16dp"
        android:paddingRight="16dp"
        android:textColor="#fff"
        android:background="?android:attr/activatedBackgroundIndicator"
        android:minHeight="?android:attr/listPreferredItemHeightSmall"/>

Das schien mir nicht viel zu sein, aber es hat den Trick getan, und ich habe meinen Java-Code überhaupt nicht geändert. Es war alles in der XML.

DroidCrafter
quelle
2

Sie fügen ein Viewin ein hinzu layout, aber die Ansicht befindet sich bereits in einem anderen layout. Eine Ansicht kann sich nicht an mehr als einem Ort befinden.

Anfänger
quelle
Ich habe meiner Frage weitere Details hinzugefügt. Kannst du das bitte sehen?
Haythem Souissi
1

Diese Lösung kann helfen:

public class FragmentItem extends Android.Support.V4.App.Fragment
{
    View rootView;
    TextView textView;

    public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        if (rootView != null) 
        {
            ViewGroup parent = (ViewGroup)rootView.Parent;
            parent.RemoveView(rootView);
        } else {
            rootView = inflater.Inflate(Resource.Layout.FragmentItem, container, false);
            textView = rootView.FindViewById<TextView>(Resource.Id.textViewDisplay);            
        }
        return rootView;
    }
}
Bhavit S. Sengar
quelle
1
Ich denke, rootView wird immer null sein, da Sie es nicht initialisiert haben.
Zin Win Htet
rootView immer null sein
Thinsky
1

Ich löste es durch das Setzen attachToRootvon inflater.inflate()zu false.

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment_overview, container, false);
    return view;
}
Herr B.
quelle
0

In Ihrer XML-Datei sollten Sie layout_width und layout_height von wrap_content auf match_parent setzen. es ist für mich behoben.

<FrameLayout
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
Evan Ngo
quelle