java.lang.IllegalStateException: el hijo especificado ya tiene un padre

99

Estoy usando fragmentos, cuando instancia un fragmento la primera vez. pero la segunda vez obtuve esta excepción. ¿No pude encontrar la línea donde obtuve el error?

 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)

Esto es lo que hago cuando hago clic en un elemento de mi fragmento de lista.

// 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 primera vez que está bien, hago clic en element2 de la lista, también está bien; pero cuando vuelvo a element1 tengo este error.

¡Gracias a todos!

haythem souissi
fuente
necesita llamar a layoutView.removeAllViews (); antes de agregar vistas al diseño
ρяσѕρєя K
@imrankhan mal! Puede agregar sin eliminar todo. Falta la parte más importante y como no hay un paquete personalizado en el stacktrace, le sugiero que elimine algún código y lo pruebe paso a paso ...
WarrenFaith
1
agrego más detalles, ¿puedes ver eso?
haythem souissi
¿Qué es esta clase RouteSearchFragment? No puedo encontrar ninguna referencia en los documentos de Android. Actualice también la definición de clase.
Noob

Respuestas:

36

Cuando anula OnCreateViewen su RouteSearchFragmentclase, tiene el

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

segmento de código?

Si es así, eliminar la declaración de devolución debería resolver su problema.

Puede conservar el código y devolver la vista si no desea volver a generar los datos de la vista, y el método onDestroyView () elimina esta vista de su padre así:

    @Override
    public void onDestroyView() {
        super.onDestroyView();
        if (view != null) {
            ViewGroup parent = (ViewGroup) view.getParent();
            if (parent != null) {
                parent.removeAllViews();
            }
        }
    }
Medo
fuente
5
@Override public void onDestroyView () {super.onDestroyView (); ViewGroup parentViewGroup = (ViewGroup) mRoutesSearchViewContainer.getParent (); if (null! = parentViewGroup) {parentViewGroup.removeView (mRoutesSearchViewContainer); }}
haythem souissi
@Medo: ¿Puedes dar una breve explicación para esto? Tengo el mismo error que se muestra en logcat. como ha dado la sugerencia "eliminar la declaración de retorno debería resolver su problema", pero necesitamos devolver el objeto View en el método onCreateView (). ¿Puede proporcionar un fragmento de código para su explicación? Gracias.
Krishna Prasad
@Krishna Simplemente infle y devuelva la vista como lo haría normalmente. Puede omitir la declaración if completa.
Medo
65
Para mí, solo tuve que reemplazarlo return inflater.inflate(R.layout.fragment_search, container);conreturn inflater.inflate(R.layout.fragment_search, container, false);
Sufian
370

Lamento publicar una pregunta anterior, pero pude solucionarlo con una solución totalmente diferente. Recibí esta excepción, pero cambié la primera línea de mi anulación onCreatView de esto:

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

...a esto:

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

No tengo idea de por qué, pero el uso de la anulación que acepta el booleano como tercer parámetro lo solucionó. Creo que le dice al Fragmento y / o Actividad que no use el "contenedor" como padre de la Vista recién creada.

Patricio
fuente
53
No se arrepienta, esto fue muy útil para mí y, claramente, para otras personas. ¡Gracias!
entrar en los códigos
Muchas gracias, sigo olvidando esto y volviendo a esta respuesta
noloman
@Patrick, el primero adjunta la vista inflada al contenedor, agregando la bandera falsa especifica que no desea agregar la vista inflada al contenedor.
Ne0
y sigo volviendo a esta publicación y descubriendo que esta es LA RESPUESTA :)
noloman
45

Me he enfrentado a este problema muchas veces. Agregue el siguiente código para resolver este problema:

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

Gracias

Hardik
fuente
Gracias por esta solución :) Tengo un caso muy específico en el que no puedo usar el inflador para resolver esto. Me ahorraste mucho tiempo
Bojan
Lo siento, no entiendo del todo porque soy nuevo en Android.
Zin Win Htet
In view.getParent (); ¿De dónde viene el objeto de vista de dosis?
Zin Win Htet
Cristy YG: Tome una instancia de View como variable global e infle su diseño xml en la variable global anterior. me estas siguiendo o no?
Hardik
Sí, ver la instancia declarar como global.
Hardik
35

Si tiene esta declaración ...

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

Entonces intente esto .. Agregue falso como tercer argumento .. Puede ser que pueda ayudar ..

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

Tenía este código en un fragmento y fallaba si intento volver a este fragmento

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

después de recopilar las respuestas en este hilo, me di cuenta de que el padre de mRootView todavía tiene mRootView como hijo. Entonces, esta fue mi solución.

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

espero que esto ayude

usuario1736525
fuente
2
+1 me ayudó. Especialmente cierto si su actividad se mantiene, pero el administrador de fragmentos agrega nuevos fragmentos en la parte superior. cuando vuelva al primer fragmento, debe asegurarse de que se elimine la vista raíz anterior. ¡Gracias!
Bundeeteddee
Me ayudó mucho. He estado encontrando esa solución durante 3 días. Respuesta simple y bonita.
Zin Win Htet
¡Guauu! finalmente funcionó para mí! gran solución. ¡Gracias!
avisper
No tengo una razón fundamental por la que "(ViewGroup) mRootView.getParent ()). RemoveView (mRootView);" funciona en contraste con llamar directamente "<WhateverIsParentViewGroupName> .removeView (mRootView)" Pero esto también funciona para mí, estoy probando en Android 8.0 y 9.0. Gracias bud ^
Khay
16

También sucede cuando la vista devuelta por onCreateView () no es la vista que se infló.

Ejemplo:

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;

Reparar:

return rootView;

En vez de:

return textView; // or whatever you returned
Mateus Pires
fuente
¡Gracias! ¡Me ayudó!
Sudheesh Mohan
5

Tuve este problema y no pude resolverlo en código Java. El problema fue con mi xml.

Estaba intentando agregar un textView a un contenedor, pero había envuelto el textView dentro de un LinearLayout.

Este era el archivo xml original:

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

Ahora con el LinearLayout eliminado:

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

Esto no me pareció mucho, pero funcionó y no cambié mi código Java en absoluto. Todo estaba en xml.

DroidCrafter
fuente
2

Está agregando a Viewen a layout, pero la Vista ya está en otra layout. Una vista no puede estar en más de un lugar.

novato
fuente
Agregué más detalles a mi pregunta, ¿pueden ver eso?
haythem souissi
1

Esta solución puede ayudar:

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
fuente
1
Creo que rootView siempre será nulo ya que no lo inicializó.
Zin Win Htet
rootView siempre será nulo
Thinsky
1

Lo resolví configurando attachToRoot de 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;
}
Sr. B.
fuente
0

en su archivo xml debe establecer layout_width y layout_height de wrap_content a match_parent. está arreglado para mí.

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