studio programacion para móviles libro edición desarrollo desarrollar curso aprende aplicaciones android android-fragments android-listfragment

para - manual de programacion android pdf



Error al inflar el fragmento de clase-duplicado id/illegalargumentexception? (7)

Intento hacer que una aplicación que estoy construyendo tome un término de búsqueda de la actividad principal, devolver resultados y luego hacer clic en los resultados para que se pueda ver un detalle de cada resultado. Lo hago utilizando MainActivity, a ResultsActivity y PlaceActivity y luego a ListFragmentClickable (que amplía ListFragment). Si el teléfono está orientado en modo vertical, la lista de resultados debe poder verse, y los detalles se visualizan solo si se hace clic en un resultado. Si el teléfono es horizontal, una ventana de detalle debe aparecer a la derecha de la lista cuando se selecciona un elemento.

En tiempo de ejecución, aparece un error que dice "error inflando el fragmento de clase". No tengo idea de qué lo está causando, y me encantaría ayudar a deshacerme de él.

My ListFragmentClickables es llamado por mi ResultsActivity, que está aquí:

public class ResultsActivity extends FragmentActivity implements ListFragmentClickable.OnItemSelectedListener{ private ArrayAdapter<String> mAdapter; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_results_view); //Receive searchTerm from MainActivity Intent intent = getIntent(); String searchTerm = intent.getStringExtra(MainActivity.SEARCH_TERM); mAdapter = new ArrayAdapter<String>(this, R.layout.item_label_list); FragmentManager fm = getSupportFragmentManager(); FragmentTransaction ft = fm.beginTransaction(); FactualResponderFragment responder = (FactualResponderFragment) fm.findFragmentByTag("RESTResponder"); if (responder == null) { responder = new FactualResponderFragment(); ft.add(responder, "RESTResponder"); } Bundle bundle = new Bundle(); bundle.putString("search_term", searchTerm); responder.setArguments(bundle); ft.commit(); } public ArrayAdapter<String> getArrayAdapter() { return mAdapter; } @Override //creates a DetailFragment when a list item is selected public void onItemSelected(String link) { DetailFragment fragment = (DetailFragment) getSupportFragmentManager().findFragmentById(R.id.detailFragment); if (fragment != null && fragment.isInLayout()) { fragment.setText(link); } else { Intent intent = new Intent(getApplicationContext(), PlaceActivity.class); intent.putExtra(PlaceActivity.EXTRA_URL, link); startActivity(intent); } }

}

Aquí está la clase ListFragmentClickable:

public class ListFragmentClickable extends ListFragment{ private OnItemSelectedListener listener; public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.activity_results_view, container, false); return view; } @Override public void onListItemClick(ListView l, View v, int position, long id) { updateDetail(); //see bottom } public interface OnItemSelectedListener { public void onItemSelected(String link); } @Override public void onAttach(Activity activity) { super.onAttach(activity); if (activity instanceof OnItemSelectedListener) { listener = (OnItemSelectedListener) activity; } else { throw new ClassCastException(activity.toString() + " must implemenet ListFragmentClickable.OnItemSelectedListener"); } } public void updateDetail() { // Create fake data String newTime = String.valueOf(System.currentTimeMillis()); // Send data to Activity listener.onItemSelected(newTime); //should direct PlaceActivity!! } }

Aquí está mi archivo de diseño para ResultsActivity (activity_results_activity.xml):

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal" > <fragment android:id="@+id/fragment_content" android:layout_width="0dp" android:layout_weight="1" android:layout_height="match_parent" android:layout_marginTop="?android:attr/actionBarSize" class="com.example.blobtag2.ListFragmentClickable" ></fragment> <ListView android:id="@android:id/list" android:layout_width="fill_parent" android:layout_height="50dp" android:divider="#b5b5b5" android:dividerHeight="1dp"></ListView> </LinearLayout>

Y finalmente aquí está el registro:

03-21 22:32:03.297: E/AndroidRuntime(764): FATAL EXCEPTION: main 03-21 22:32:03.297: E/AndroidRuntime(764): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.blobtag2/com.example.blobtag2.ResultsActivity}: android.view.InflateException: Binary XML file line #7: Error inflating class fragment 03-21 22:32:03.297: E/AndroidRuntime(764): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2059) 03-21 22:32:03.297: E/AndroidRuntime(764): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084) 03-21 22:32:03.297: E/AndroidRuntime(764): at android.app.ActivityThread.access$600(ActivityThread.java:130) 03-21 22:32:03.297: E/AndroidRuntime(764): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195) 03-21 22:32:03.297: E/AndroidRuntime(764): at android.os.Handler.dispatchMessage(Handler.java:99) 03-21 22:32:03.297: E/AndroidRuntime(764): at android.os.Looper.loop(Looper.java:137) 03-21 22:32:03.297: E/AndroidRuntime(764): at android.app.ActivityThread.main(ActivityThread.java:4745) 03-21 22:32:03.297: E/AndroidRuntime(764): at java.lang.reflect.Method.invokeNative(Native Method) 03-21 22:32:03.297: E/AndroidRuntime(764): at java.lang.reflect.Method.invoke(Method.java:511) 03-21 22:32:03.297: E/AndroidRuntime(764): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786) 03-21 22:32:03.297: E/AndroidRuntime(764): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553) 03-21 22:32:03.297: E/AndroidRuntime(764): at dalvik.system.NativeStart.main(Native Method) 03-21 22:32:03.297: E/AndroidRuntime(764): Caused by: android.view.InflateException: Binary XML file line #7: Error inflating class fragment 03-21 22:32:03.297: E/AndroidRuntime(764): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:704) 03-21 22:32:03.297: E/AndroidRuntime(764): at android.view.LayoutInflater.rInflate(LayoutInflater.java:746) 03-21 22:32:03.297: E/AndroidRuntime(764): at android.view.LayoutInflater.inflate(LayoutInflater.java:489) 03-21 22:32:03.297: E/AndroidRuntime(764): at android.view.LayoutInflater.inflate(LayoutInflater.java:396) 03-21 22:32:03.297: E/AndroidRuntime(764): at com.example.blobtag2.ListFragmentClickable.onCreateView(ListFragmentClickable.java:32) 03-21 22:32:03.297: E/AndroidRuntime(764): at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:846) 03-21 22:32:03.297: E/AndroidRuntime(764): at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1061) 03-21 22:32:03.297: E/AndroidRuntime(764): at android.support.v4.app.FragmentManagerImpl.addFragment(FragmentManager.java:1160) 03-21 22:32:03.297: E/AndroidRuntime(764): at android.support.v4.app.FragmentActivity.onCreateView(FragmentActivity.java:272) 03-21 22:32:03.297: E/AndroidRuntime(764): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:676) 03-21 22:32:03.297: E/AndroidRuntime(764): at android.view.LayoutInflater.rInflate(LayoutInflater.java:746) 03-21 22:32:03.297: E/AndroidRuntime(764): at android.view.LayoutInflater.inflate(LayoutInflater.java:489) 03-21 22:32:03.297: E/AndroidRuntime(764): at android.view.LayoutInflater.inflate(LayoutInflater.java:396) 03-21 22:32:03.297: E/AndroidRuntime(764): at android.view.LayoutInflater.inflate(LayoutInflater.java:352) 03-21 22:32:03.297: E/AndroidRuntime(764): at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:256) 03-21 22:32:03.297: E/AndroidRuntime(764): at android.app.Activity.setContentView(Activity.java:1867) 03-21 22:32:03.297: E/AndroidRuntime(764): at com.example.blobtag2.ResultsActivity.onCreate(ResultsActivity.java:37) 03-21 22:32:03.297: E/AndroidRuntime(764): at android.app.Activity.performCreate(Activity.java:5008) 03-21 22:32:03.297: E/AndroidRuntime(764): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079) 03-21 22:32:03.297: E/AndroidRuntime(764): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2023) 03-21 22:32:03.297: E/AndroidRuntime(764): ... 11 more 03-21 22:32:03.297: E/AndroidRuntime(764): Caused by: java.lang.IllegalArgumentException: Binary XML file line #7: Duplicate id 0x7f070003, tag null, or parent id 0x0 with another fragment for com.example.blobtag2.ListFragmentClickable 03-21 22:32:03.297: E/AndroidRuntime(764): at android.support.v4.app.FragmentActivity.onCreateView(FragmentActivity.java:277) 03-21 22:32:03.297: E/AndroidRuntime(764): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:676) 03-21 22:32:03.297: E/AndroidRuntime(764): ... 30 more

Cualquier y toda ayuda es enormemente apreciada. Por favor, avíseme si hay algo más que pueda agregar.


El problema es que el fragmento en xml se carga dos veces, y la segunda vez que se agrega al FragmentManager se obtiene una IllegalArgumentException. Tengo el mismo problema ayer.

Mi solución, la cambio para volver a crear el fragmento de forma dinámica en lugar de definirlo en el archivo xml:

Cambie esta parte del archivo xml:

<fragment android:id="@+id/fragment_content" android:layout_width="0dp" android:layout_weight="1" android:layout_height="match_parent" android:layout_marginTop="?android:attr/actionBarSize" class="com.example.blobtag2.ListFragmentClickable" ></fragment>

Para esto en su lugar:

<FrameLayout android:id="@+id/fragment_content" android:layout_width="0dp" android:layout_weight="1" android:layout_height="match_parent" android:layout_marginTop="?android:attr/actionBarSize" />

Luego, en onCreate, debes reemplazar FrameLayout por un nuevo fragmento:

Fragment fragment = new ListFragmentClickable(); FragmentManager fm = getSupportFragmentManager(); FragmentTransaction ft = fm.beginTransaction(); ft.replace(R.id.fragment_content, fragment); ft.commit();

Y luego tienes lo mismo, pero no obtendrás un error de ID duplicado.


Esta línea

03-21 22:32:03.297: E/AndroidRuntime(764): Caused by: java.lang.IllegalArgumentException: Binary XML file line #7: Duplicate id 0x7f070003, tag null, or parent id 0x0 with another fragment for com.example.blobtag2.ListFragmentClickable

específicamente la parte al final

Duplicate id 0x7f070003, tag null, or parent id 0x0 with another fragment for com.example.blobtag2.ListFragmentClickable

le dice que en algún punto de la vida de su actividad intenta crear una vista para ListFragmentClickable cuando ya existe. Necesitas descubrir cómo está ocurriendo esto.


Ocurre cuando los fragmentos se definen en XML (estáticamente): FragmentManager no administra fragmentos secundarios si se destruye el fragmento principal. Luego, se rompe (error de "identificación duplicada") cuando el XML se infla por segunda vez.

Evito este problema al eliminar el fragmento XML manualmente cuando se destruye el elemento primario , con este código en el fragmento principal:

@Override public void onDestroyView() { FragmentManager fm = getFragmentManager(); Fragment xmlFragment = fm.findFragmentById(R.id.XML_FRAGMENT_ID); if (xmlFragment != null) { fm.beginTransaction().remove(xmlFragment).commit(); } super.onDestroyView(); }

Nota para copiadores : XML_FRAGMENT_ID es la identificación del fragmento en el XML;)

Además, prefiero una nueva clase que envuelva fragmentos XML . Simplemente simplifica el código ya que solo necesita extender su clase de fragmento desde él. Agregue esta clase a su proyecto:

package net.treboada.mytests.fragments; import android.app.Activity; import android.os.Bundle; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.util.AttributeSet; public class XmlFragment extends Fragment { @Override public void onInflate(Activity activity, AttributeSet attrs, Bundle savedInstanceState) { FragmentManager fm = getFragmentManager(); if (fm != null) { fm.beginTransaction().remove(this).commit(); } super.onInflate(activity, attrs, savedInstanceState); } }

Luego, amplíe sus clases de fragmentos XML:

package net.treboada.mytests.fragments; public class TestXmlFragment01 extends XmlFragment { // ... }

¡y voilá! :)


Probemos esto. Tengo el mismo problema y arreglé mi problema usando este código.

View root; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { if (root!= null) { ViewGroup parent = (ViewGroup) root.getParent(); if (parent != null) parent.removeView(root); } try { root= inflater.inflate(R.layout.map_layout, container, false); } catch (InflateException e) { /* map is already there, just return view as it is */ } return root; }


Puede extender su fragmento (que carga en xml) desde XmlFragment. Maneja el FragmentManager principal y se elimina solo.

public class XmlFragment extends BaseFragment { @Override public void onDestroyView() { Fragment parentFragment = getParentFragment(); FragmentManager manager; if (parentFragment != null) { // If parent is another fragment, then this fragment is nested manager = parentFragment.getChildFragmentManager(); } else { // This fragment is placed into activity manager = getActivity().getSupportFragmentManager(); } manager.beginTransaction().remove(this).commitAllowingStateLoss(); super.onDestroyView(); } }


Si estaba leyendo las otras respuestas aquí sintiendo que parecían correctas, mire aquí https://.com/a/19815266/1139784 porque hace referencia a la documentación que explica cómo esto no es compatible (al menos en mi caso, es difícil) contar a partir de esta pregunta si está ocurriendo la anidación de fragmento de disposición)

Note: You cannot inflate a layout into a fragment when that layout includes a <fragment>. Nested fragments are only supported when added to a fragment dynamically.

Más datos aquí Práctica recomendada para fragmentos anidados en Android 4.0, 4.1 (<4.2) sin utilizar la biblioteca de soporte

Editar: Además, si está considerando usar fragmentos anidados y no necesita la administración del ciclo de vida, puede crear un grupo de vista personalizado (como extender LinearLayout) en su lugar. http://www.vogella.com/tutorials/AndroidCustomViews/article.html


Tuve el mismo problema con el fragmento llamado dos veces y en la segunda vez que se estrelló. La solución es implementar la instrucción remove en el método onDetach:

@override public void onDetach(){ super.onDetach(); FragmentManager fm = getFragmentManager() Fragment xmlFragment = fm.findFragmentById(R.id.yourfragmentid); if(xmlFragment != null){ fm.beginTransaction().remove(xmlFragment).commit(); } }