IllegalStateException al reemplazar un Fragmento

Es una pequeña aplicación de prueba de Android 2.2 que usa el paquete de compatibilidad. Esta es la forma (incorrecta, por supuesto) en que bash reemplazar un Fragmento cuando recibo un clic. Estoy tratando de reemplazarlo con una nueva instancia (diferente) de la misma clase Fragment. Como explicaré, no funciona como se esperaba y necesito ayuda:

public class MainFragmentActivity extends FragmentActivity { ... public void myAction(View view) { ... RightFragment newRightFrag = RightFragment.newInstance(myNewOption); FragmentTransaction ft = getSupportFragmentManager().beginTransaction(); ft.setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out); ft.replace(R.id.landscape_right_fragment, newRightFrag); ft.commit(); } } 

Seguramente habrás visto cuál es mi error. De todos modos, démosle un poco más de explicación sobre lo que debería hacer la aplicación:

Orientación horizontal :

 --------- ---------- | L | R | -> click -> | L | R2 | --------- ---------- 

En orientación horizontal, la actividad tiene una vista con 2 fragmentos: ” leftLand ” y ” rightLand “, y si haces clic en un botón del fragmento ” leftLand “, cambia creando un nuevo Fragment y sustituye la instancia Fragment ” rightLand ” con otra instancia de la misma clase FragamentActivity. Lo que hace que esas dos instancias sean diferentes es un parámetro pasado a “newInstance (int)”, se basa en el botón presionado.

Orientación Vertical :

 ----- ----- | | | | | L | -> click -> | R | | | | | ----- ----- 

En orientación vertical solo muestra el fragmento ” leftPort ” (tiene el mismo diseño que ” leftLand “) y si hace clic en su botón, se inicia Intent y se inicia RightFragmentActivity, que muestra el Fragment ” rightLand

Funciona bien … si no reemplazo el fragmento correcto. Si lo hago (haciendo clic en el botón en orientación horizontal), luego en un cambio de orientación posterior (reinicio de la actividad) FragmentActivity no se puede iniciar debido a una ” IllegalStateException: Fragment RightFragment did not create a view como esta:

 D/AndroidRuntime( 1428): Shutting down VM W/dalvikvm( 1428): threadid=1: thread exiting with uncaught exception (group=0x4001d800) E/AndroidRuntime( 1428): FATAL EXCEPTION: main E/AndroidRuntime( 1428): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.agm.test/com.agm.test.MainFragmentActivity}: android.view.InflateException: Binary XML file line #13: Error inflating class fragment E/AndroidRuntime( 1428): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2663) E/AndroidRuntime( 1428): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2679) E/AndroidRuntime( 1428): at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3815) E/AndroidRuntime( 1428): at android.app.ActivityThread.access$2400(ActivityThread.java:125) E/AndroidRuntime( 1428): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2037) E/AndroidRuntime( 1428): at android.os.Handler.dispatchMessage(Handler.java:99) E/AndroidRuntime( 1428): at android.os.Looper.loop(Looper.java:123) E/AndroidRuntime( 1428): at android.app.ActivityThread.main(ActivityThread.java:4627) E/AndroidRuntime( 1428): at java.lang.reflect.Method.invokeNative(Native Method) E/AndroidRuntime( 1428): at java.lang.reflect.Method.invoke(Method.java:521) E/AndroidRuntime( 1428): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868) E/AndroidRuntime( 1428): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626) E/AndroidRuntime( 1428): at dalvik.system.NativeStart.main(Native Method) E/AndroidRuntime( 1428): Caused by: android.view.InflateException: Binary XML file line #13: Error inflating class fragment E/AndroidRuntime( 1428): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:582) E/AndroidRuntime( 1428): at android.view.LayoutInflater.rInflate(LayoutInflater.java:618) E/AndroidRuntime( 1428): at android.view.LayoutInflater.inflate(LayoutInflater.java:407) E/AndroidRuntime( 1428): at android.view.LayoutInflater.inflate(LayoutInflater.java:320) E/AndroidRuntime( 1428): at android.view.LayoutInflater.inflate(LayoutInflater.java:276) E/AndroidRuntime( 1428): at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:198) E/AndroidRuntime( 1428): at android.app.Activity.setContentView(Activity.java:1647) E/AndroidRuntime( 1428): at com.agm.test.MainFragmentActivity.onCreate(MainFragmentActivity.java:25) E/AndroidRuntime( 1428): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047) E/AndroidRuntime( 1428): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2627) E/AndroidRuntime( 1428): ... 12 more E/AndroidRuntime( 1428): Caused by: java.lang.IllegalStateException: Fragment com.agm.test.RightFragment did not create a view. E/AndroidRuntime( 1428): at android.support.v4.app.FragmentActivity.onCreateView(FragmentActivity.java:287) E/AndroidRuntime( 1428): at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:558) E/AndroidRuntime( 1428): ... 21 more W/ActivityManager( 59): Force finishing activity com.agm.test/.MainFragmentActivity 

Me di cuenta de que el antiguo ” RightFragment ” no se destruye después de haber sido reemplazado. Esto es probablemente una consecuencia de mi manera incorrecta de tratar de sustituirlo.

Cualquier ayuda sería realmente apreciada.

¡Gracias por adelantado!

/ Angel Galindo Muñoz

Creo que es posible que haya malinterpretado mi comentario, por lo que ofreceré una explicación más detallada aquí.

Un problema que comúnmente surge al eliminar o reemplazar fragmentos es tratar de eliminar un fragmento que se ha agregado al diseño a través de XML en lugar de hacerlo mediante progtwigción en Java. Esto no es lo mismo que inflar el propio diseño del fragmento en la función onCreateView() del código Java del fragmento (esto es lo que parece estar describiendo en su respuesta a mi comentario). Para ilustrar de lo que estoy hablando, te mostraré dos formas en que las personas intentan eliminar / reemplazar fragmentos.

Esta es la forma incorrecta de hacerlo:

Diseño XML:

    

Java:

 swapFragment() { Fragment newFragment = new ExampleFragment(); FragmentTransaction transaction = getFragmentManager().beginTransaction(); transaction.replace(R.id.fragment_container, newFragment); transaction.addToBackStack(null); transaction.commit(); } 

Este código no se ejecutará de la manera que esperas. El fragmento inicial que se agrega en el diseño XML no se eliminará. Esto se debe a que los diseños XML están destinados a describir elementos de diseño estáticos. Puede cambiar sus contenidos en tiempo de ejecución u ocultarlos, pero no puede eliminarlos del diseño. Esto es lo que Dianne Hackborn decía en el hilo de discusión al que me he vinculado anteriormente.

Esta es la forma correcta de hacerlo (al menos en mi experiencia):

Diseño XML:

    

Java:

 protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.my_layout); ExampleFragment newFragment = new ExampleFragment(); FragmentTransaction transaction = getFragmentManager().beginTransaction(); transaction.add(R.id.fragment_container, newFragment); transaction.commit(); } 

 swapFragment() { Fragment newFragment = new ExampleFragment(); FragmentTransaction transaction = getFragmentManager().beginTransaction(); transaction.replace(R.id.fragment_container, newFragment); transaction.addToBackStack(null); transaction.commit(); } 

Esta estrategia no agrega el fragmento en el diseño inicial. En cambio, lo agrega al código de Java cuando se crea la actividad. Esto permite que se elimine del diseño (ya sea utilizando remove() o replace() )

Esto podría no resolver su problema, pero es una dificultad común que crean los Fragmentos. Puede asegurarse de que está agregando los Fragmentos de la manera adecuada para permitir que se eliminen y, si eso no resuelve el problema, podemos solucionarlo más.

hay otra manera, cuando desarrolles aplicaciones para tabletas con pantallas grandes, puedes inflar diferentes diseños para cada orientación de la pantalla. Solo tienes que crear los dos diseños y nombrarlos con retrato o paisaje, en “Crear” simplemente inflas el xml de acuerdo con la orientación.

en el evento onClick solo identifique la orientación con: getResources (). getConfiguration (). orientation

y haz tus cosas