java.lang.IllegalStateException: il figlio specificato ha già un genitore


99

Sto usando i frammenti, quando istanzio un frammento la prima volta che lo installo. ma la seconda volta ho avuto questa eccezione. Non sono riuscito a trovare la riga in cui ho ricevuto l'errore?

 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)

Ecco cosa faccio quando clicco su un elemento del mio frammento di elenco.

// 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 prima volta che è OK, faccio clic su element2 dall'elenco, è anche ok; ma quando torno a element1 ho ricevuto questo bug.

Grazie a tutti!


è necessario chiamare layoutView.removeAllViews (); prima di aggiungere viste al layout
ρяσsρєя K

@imrankhan sbagliato! Puoi aggiungere senza rimuovere tutto. Manca la parte più importante e poiché non esiste un pacchetto personalizzato nello stacktrace, ti suggerisco di rimuovere un po 'di codice e testarlo passo dopo passo ...
WarrenFaith

1
aggiungo ulteriori dettagli, per favore potete vederlo?
haythem souissi

Cos'è questa classe RouteSearchFragment ?? Non riesco a trovare alcun riferimento nei documenti Android. Aggiorna anche la definizione della classe.
noob

Risposte:


36

Quando esegui l'override OnCreateViewnella tua RouteSearchFragmentclasse, hai l'estensione

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

segmento di codice?

In tal caso, la rimozione dell'istruzione di reso dovrebbe risolvere il problema.

Puoi mantenere il codice e restituire la vista se non vuoi rigenerare i dati della vista, e sul metodoDestroyView () rimuovi questa vista dal suo genitore in questo modo:

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

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

@Medo: puoi dare una breve spiegazione per questo. Ho lo stesso errore mostrato nel logcat. come hai dato il suggerimento "rimuovere l'istruzione return dovrebbe risolvere il tuo problema" ma dobbiamo restituire l'oggetto View nel metodo onCreateView (). puoi fornire uno snippet di codice per la tua spiegazione. Grazie.
Krishna Prasad

@Krishna Basta gonfiare e restituire la vista come faresti normalmente. Puoi saltare l'intera istruzione if.
Medo

65
Per me, ho dovuto sostituire return inflater.inflate(R.layout.fragment_search, container);conreturn inflater.inflate(R.layout.fragment_search, container, false);
Sufian

370

Mi dispiace postare una vecchia domanda ma sono riuscito a risolverla utilizzando una soluzione completamente diversa. Stavo ottenendo questa eccezione ma ho cambiato la prima riga del mio override onCreatView da questo:

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

...a questa:

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

Non ho idea del perché, ma utilizzando l'override che accetta il booleano come terzo parametro lo ha risolto. Penso che dica al frammento e / o all'attività di non utilizzare il "contenitore" come genitore della vista appena creata.


53
Non scusarti: questo è stato molto utile per me e chiaramente per molte altre persone. Grazie!
vai nei codici

Grazie mille, continuo a dimenticarlo e tornare a questa risposta
noloman

@Patrick, il primo collega la vista gonfiata al container, aggiungendo la falsa bandiera si specifica che non si desidera aggiungere la vista gonfiata al container.
Ne0

e continuo a tornare su questo post e scoprire che questa è LA RISPOSTA :)
noloman

45

Ho affrontato questo problema molte volte. Si prega di aggiungere il seguente codice per risolvere questo problema:

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

Grazie


Grazie per questa soluzione :) Ho un caso molto specifico in cui non posso usare inflater per risolvere questo problema. Mi hai risparmiato un sacco di tempo
Bojan

Mi dispiace, non capisco bene perché sono nuovo su Android.
Zin Win Htet

In view.getParent (); Da dove provengono gli oggetti dose view?
Zin Win Htet

Cristy YG: prendi un'istanza View come variabile globale e gonfia il tuo layout xml sulla variabile globale sopra. mi stai seguendo o no?
Hardik

Sì, visualizza l'istanza dichiarata come globale.
Hardik

35

Se hai questa dichiarazione ..

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

Quindi prova questo .. Aggiungi false come terzo argomento .. Potrebbe essere d'aiuto ..

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

21

Avevo questo codice in un frammento e si stava bloccando se provo a tornare a questo frammento

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

dopo aver raccolto le risposte su questo thread, mi sono reso conto che il genitore di mRootView ha ancora mRootView come figlio. Quindi, questa era la mia soluzione.

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

spero che questo ti aiuti


2
+1 mi ha aiutato. Soprattutto se la tua attività rimane ma il gestore dei frammenti aggiunge nuovi frammenti in cima. quando torna al primo frammento, è necessario assicurarsi che la vecchia vista root venga rimossa. Grazie!
Bundeeteddee

Mi ha aiutato molto. Ho trovato quella soluzione per 3 giorni. Risposta semplice e carina.
Zin Win Htet

Wow! finalmente ha funzionato per me! ottima soluzione. Grazie!
Avisper

Non ho una motivazione per cui "(ViewGroup) mRootView.getParent ()). RemoveView (mRootView);" funziona in contrasto con la chiamata diretta di "<WutelyIsParentViewGroupName> .removeView (mRootView)" Ma questo funziona anche per me, sto testando su Android 8.0 e 9.0. Grazie amico ^
Khay

16

Succede anche quando la vista restituita da onCreateView () non è la vista che è stata gonfiata.

Esempio:

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;

Correzione:

return rootView;

Invece di:

return textView; // or whatever you returned

Grazie! mi ha aiutato!
Sudheesh Mohan

5

Ho avuto questo problema e non sono riuscito a risolverlo nel codice Java. Il problema era con il mio xml.

Stavo cercando di aggiungere un textView a un contenitore, ma avevo avvolto il textView all'interno di un LinearLayout.

Questo era il file xml originale:

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

Ora con LinearLayout rimosso:

<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"/>

Questo non mi è sembrato molto, ma ha funzionato e non ho cambiato affatto il mio codice Java. Era tutto in xml.


2

Stai aggiungendo un Viewin a layout, ma la View è già in un altro layout. Una vista non può essere in più di un posto.


ho aggiunto maggiori dettagli alla mia domanda, puoi vederlo?
haythem souissi

1

Questa soluzione può aiutare:

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;
    }
}

1
Penso che rootView sarà sempre nullo poiché non lo hai inizializzato.
Zin Win Htet

rootView sarà sempre nullo
Thinsky

1

Ho risolto impostando attachToRootdi inflater.inflate()a false.

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

0

nel tuo file xml dovresti impostare layout_width e layout_height da wrap_content a match_parent. è risolto per me.

<FrameLayout
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.