java.lang.IllegalStateException: określone dziecko ma już rodzica

99

Używam fragmentów, kiedy tworzę instancję fragmentu po raz pierwszy. ale za drugim razem dostałem ten wyjątek. Nie mogłem znaleźć linii, w której pojawił się błąd?

 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)

Oto, co robię, gdy klikam element mojej listy.

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

Za pierwszym razem OK, klikam element2 z listy, też jest ok; ale kiedy wracam do elementu 1, mam ten błąd.

Dziękuję wszystkim!

haythem souissi
źródło
trzeba wywołać layoutView.removeAllViews (); przed dodaniem widoków do układu
ρяσѕρєя K
@imrankhan źle! Możesz dodać bez usuwania wszystkich. Brakuje najważniejszej części, a ponieważ w ścieżce stosu nie ma niestandardowego pakietu, sugeruję usunięcie kodu i przetestowanie go krok po kroku ...
WarrenFaith
1
dodaję więcej szczegółów, czy widzisz to?
haythem souissi
Co to za klasa RouteSearchFragment? Nie można znaleźć żadnego odniesienia w dokumentach Androida. Zaktualizuj też definicję klasy.
noob

Odpowiedzi:

36

Kiedy nadpisujesz OnCreateVieww swojej RouteSearchFragmentklasie, czy masz

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

segment kodu?

Jeśli tak, usunięcie instrukcji return powinno rozwiązać problem.

Możesz zachować kod i zwrócić widok, jeśli nie chcesz ponownie generować danych widoku, a metoda onDestroyView () usuniesz ten widok z jego rodzica w następujący sposób:

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        if (view != null) {
            ViewGroup parent = (ViewGroup) view.getParent();
            if (parent != null) {
                parent.removeAllViews();
            }
        }
    }
Medo
źródło
5
@Override public void onDestroyView () {super.onDestroyView (); ViewGroup parentViewGroup = (ViewGroup) mRoutesSearchViewContainer.getParent (); if (null! = parentViewGroup) {parentViewGroup.removeView (mRoutesSearchViewContainer); }}
haythem souissi
@Medo: Czy możesz podać krótkie wyjaśnienie tego. Mam ten sam błąd pokazany w logcat. jak podałeś sugestię "usunięcie instrukcji return powinno rozwiązać twój problem", ale musimy zwrócić obiekt View w metodzie onCreateView (). czy możesz podać fragment kodu dla wyjaśnienia. Dziękuję Ci.
Krishna Prasad,
@Krishna Po prostu nadmuchaj i zwróć widok tak, jak zwykle. Możesz pominąć całą instrukcję if.
Medo,
65
Dla mnie, po prostu musiałem wymienić return inflater.inflate(R.layout.fragment_search, container);zreturn inflater.inflate(R.layout.fragment_search, container, false);
Sufian
370

Przepraszam, że piszę na stare pytanie, ale udało mi się to naprawić za pomocą zupełnie innego rozwiązania. Otrzymałem ten wyjątek, ale zmieniłem pierwszą linię mojego zastąpienia onCreatView z tego:

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

...do tego:

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

Nie mam pojęcia, dlaczego, ale użycie zastąpienia, które akceptuje wartość logiczną jako trzeci parametr, naprawiło to. Myślę, że mówi fragmentowi i / lub działaniu, aby nie używał „kontenera” jako elementu nadrzędnego nowo utworzonego widoku.

Patrick
źródło
53
Nie przepraszaj - to było bardzo przydatne dla mnie i dla wielu innych osób. Dzięki!
kieruj się kodami
Wielkie
@Patrick, Pierwszy dołącza zawyżony widok do kontenera, dodanie fałszywej flagi oznacza, że ​​nie chcesz dodawać zawyżonego widoku do kontenera.
Ne0
i ciągle wracam do tego posta i dowiaduję się, że to jest ODPOWIEDŹ :)
noloman
45

Wielokrotnie stykałem się z tym problemem. Dodaj następujący kod, aby rozwiązać ten problem:

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

Dzięki

Hardik
źródło
Dziękuję za to rozwiązanie :) Mam bardzo konkretny przypadek, w którym nie mogę użyć inflatora do rozwiązania tego problemu. Zaoszczędziłeś mi dużo czasu
Bojan
Przepraszam, nie do końca rozumiem, bo jestem nowy w Androidzie.
Zin Win Htet
W widoku.getParent (); Skąd pochodzi obiekt z widokiem dawki?
Zin Win Htet
Cristy YG: weź instancję View jako zmienną globalną i uzupełnij swój układ XML o powyższą zmienną globalną. śledzisz mnie czy nie?
Hardik
Tak, wyświetl instancję zadeklarowaną jako globalną.
Hardik
35

Jeśli masz to oświadczenie ...

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

Spróbuj tego… Dodaj fałsz jako trzeci argument… Może to pomoże…

View view = inflater.inflate(R.layout.fragment1, container, false);//correct one
Dhananjay M
źródło
21

Miałem ten kod we fragmencie i zawieszał się, gdy próbowałem wrócić do tego fragmentu

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

po zebraniu odpowiedzi w tym wątku zdałem sobie sprawę, że rodzic mRootView nadal ma mRootView jako dziecko. Więc to była moja poprawka.

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

mam nadzieję że to pomoże

user1736525
źródło
2
+1 mi pomogło. Jest to szczególnie ważne, jeśli twoja aktywność pozostaje, ale menedżer fragmentów dodaje nowe fragmenty na wierzchu. kiedy wróci do pierwszego fragmentu, upewnij się, że stary widok katalogu głównego zostanie usunięty. Dzięki!
Bundeeteddee
Bardzo mi to pomogło. To rozwiązanie znajduję od 3 dni. Prosta i ładna odpowiedź.
Zin Win Htet
Łał! w końcu to zadziałało! doskonałe rozwiązanie. dzięki!
avisper,
Nie mam uzasadnienia, dlaczego "(ViewGroup) mRootView.getParent ()). RemoveView (mRootView);" działa w przeciwieństwie do bezpośredniego wywoływania „<WhthingIsParentViewGroupName> .removeView (mRootView)” Ale to działa również dla mnie, testuję na Androidzie 8.0 i 9.0. Dzięki, bud ^
Khay,
16

Dzieje się tak również, gdy widok zwrócony przez onCreateView () nie jest widokiem, który został zawyżony.

Przykład:

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;

Naprawić:

return rootView;

Zamiast:

return textView; // or whatever you returned
Mateus Pires
źródło
Dzięki! pomogło mi!
Sudheesh Mohan
5

Miałem ten problem i nie mogłem go rozwiązać w kodzie Java. Problem był z moim xml.

Próbowałem dodać textView do kontenera, ale opakowałem textView wewnątrz LinearLayout.

To był oryginalny plik xml:

<?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>

Teraz z usuniętym 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"/>

Nie wydawało mi się to dużo, ale załatwiło sprawę i w ogóle nie zmieniłem kodu Java. Wszystko znajdowało się w pliku xml.

DroidCrafter
źródło
2

Dodajesz Viewdo a layout, ale widok jest już w innym layout. Widok nie może znajdować się w więcej niż jednym miejscu.

Nowicjusz
źródło
dodałem więcej szczegółów do mojego pytania, czy widzisz to?
haythem souissi
1

To rozwiązanie może pomóc:

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
źródło
1
Myślę, że rootView zawsze będzie null, ponieważ nie zainicjowałeś go.
Zin Win Htet,
rootView zawsze ma wartość null
Thinsky
1

Rozwiązałem go przez ustawienie attachToRootod inflater.inflate()celu false.

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View view = inflater.inflate(R.layout.fragment_overview, container, false);
    return view;
}
Pan B.
źródło
0

w pliku xml powinieneś ustawić layout_width i layout_height z wrap_content na match_parent. to jest dla mnie naprawione.

<FrameLayout
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
Evan Ngo
źródło