12

Tengo un problema muy extraño con los fragmentos. Uso la biblioteca de soporte más nueva. También uso un código similar al usado por Google en su IOSCHED projectAndroid: Duplicación de fragmentos al utilizar Support Fragment Manager

Pero tengo un problema con la recreación de la actividad después de la rotación. Después de que una actividad se destruye y se crea de nuevo, invoco métodos para gestionar la transacción de fragmento (en el método onStart). ¡Esta línea se llama solo una vez, pero crea el fragmento DOS VECES!

Este es mi método actividad:

public abstract class SinglePaneActivity extends FragmentActivity 
{ 
    @Override 
    protected void onStart() 
    { 
     super.onStart(); 

     if(mFragment == null) 
     { 
      mFragment = onCreatePane();  
      mFragment.setArguments(Utils.intentToFragmentArguments(getIntent())); 

      Log.w(TAG, "Fragment creation counter = " + createCounter); 
      createCounter++; 

      getSupportFragmentManager() 
      .beginTransaction() 
      .add(R.id.root_container,mFragment) 
      .commit(); 
     } 
    } 

    @Override 
    protected void onStop() 
    { 
     Log.i(TAG, "onStop"); 
     if(mFragment != null) 
     { 
      getSupportFragmentManager() 
      .beginTransaction() 
      .remove(mFragment) 
      .commit(); 

      mFragment = null; 
     } 
     super.onStop(); 
    } 
} 

y mis registros:

--Start of application-- 
11-18 13:26:37.050: I/SinglePaneActivity(19040): onCreate 
11-18 13:26:37.050: I/SinglePaneActivity(19040): onStart 
11-18 13:26:37.055: W/SinglePaneActivity(19040): replacing fragment, counter = 1 
11-18 13:26:37.075: I/MyFragment(19040): onCreate 
11-18 13:26:37.110: I/MyFragment(19040): onActivityCreated 
--Rotating the device-- 
11-18 13:26:39.600: I/SinglePaneActivity(19040): onStop 
11-18 13:26:39.600: I/SinglePaneActivity(19040): onDestroy 
11-18 13:26:39.605: I/MyFragment(19040): onDestroy 
11-18 13:26:39.755: I/MyFragment(19040): onCreate 
11-18 13:26:39.755: I/SinglePaneActivity(19040): onCreate 
11-18 13:26:39.790: I/MyFragment(19040): onActivityCreated 
11-18 13:26:39.800: I/SinglePaneActivity(19040): onStart 
11-18 13:26:39.800: W/SinglePaneActivity(19040): replacing fragment, counter = 2 
11-18 13:26:39.810: I/MyFragment(19040): onCreate 
11-18 13:26:39.815: I/MyFragment(19040): onActivityCreated 
--Rotating the device back-- 
11-18 13:36:47.060: I/SinglePaneActivity(19040): onStop 
11-18 13:36:47.060: I/SinglePaneActivity(19040): onDestroy 
11-18 13:36:47.060: I/MyFragment(19040): onDestroy 
11-18 13:36:47.065: I/MyFragment(19040): onDestroy 
11-18 13:36:47.130: I/MyFragment(19040): onCreate 
11-18 13:36:47.130: I/MyFragment(19040): onCreate 
11-18 13:36:47.130: I/SinglePaneActivity(19040): onCreate 
11-18 13:36:47.140: I/MyFragment(19040): onActivityCreated 
11-18 13:36:47.150: I/MyFragment(19040): onActivityCreated 
11-18 13:36:47.150: I/SinglePaneActivity(19040): onStart 
11-18 13:36:47.150: W/SinglePaneActivity(19040): replacing fragment, counter = 3 
11-18 13:36:47.160: I/MyFragment(19040): onCreate 
11-18 13:36:47.160: I/MyFragment(19040): onActivityCreated 
--Exiting the app-- 
11-18 13:36:48.880: I/SinglePaneActivity(19040): onStop 
11-18 13:36:48.885: I/SinglePaneActivity(19040): onDestroy 
11-18 13:36:48.885: I/MyFragment(19040): onDestroy 
11-18 13:36:48.890: I/MyFragment(19040): onDestroy 
11-18 13:36:48.890: I/MyFragment(19040): onDestroy 

Así el número de fragmentos está creciendo después de cada rotación.

Después de la rotación, restaura el fragmento antes de que vaya a mi método onStart y mi método onStart crea el segundo mismo fragmento en el mismo contenedor de diseño de fotogramas. ¿DONDE restaura el primer fragmento? Quiero pasarlo. ¿O debería cambiar mi "si" para probar si ya está creado? Pero no sé cómo determinarlo. Parece que la prueba nula es inútil.

También hice una pequeña solución reemplazando el método add() por replace(). Después de eso, la cantidad de fragmentos no aumenta y cada fragmento se destruye antes de crear uno nuevo en el método onStart. Pero esto causa serios problemas en algunos fragmentos donde comienzo algunos procesos en segundo plano en el método Crear ...

Por favor, ayúdame ... Realmente no tengo ni idea de qué hacer con él. ¡Muchas gracias por cualquier consejo o idea!

Respuesta

23

Bueno, encontré una solución. Tuve que mover el código con el administrador de fragmentos de onStart a onCreate y verificar el valor null de savedInstanceState. Bueno, yo no sabía que se guarda y restaura desde savedInstanceState automágicamente. ¡Bueno saber!

EDIT: y hacerlo completamente correcto, es decir, restaurar fragmento cuando savedInstanceState no es nulo, no debería ser:

if(savedInstanceState == null) 
    { 
     mFragment = onCreatePane();  
     mFragment.setArguments(Utils.intentToFragmentArguments(getIntent())); 

     getSupportFragmentManager() 
     .beginTransaction() 
     .add(R.id.root_container,mFragment) 
     .commit(); 
    } 
    else 
    { 
     mFragment = getSupportFragmentManager().findFragmentById(R.id.root_container); 
    } 
+0

Sí! Gracias. He estado luchando con el mismo problema. comprobé si había null savedInstanceState en mi actividad antes de cargar mi fragmento; el truco fue – Chiatar

-1

O si su fragmento no en la pila de vuelta: setRetainInstance(true);

+1

Esto no se recomienda. Si el fragmento contiene alguna referencia a una instancia de la actividad; directamente oa través de un miembro como una vista, esto causará pérdidas de memoria. – frostymarvelous

1

Tuve un problema similar, pero estaba agregando un fragmento hijo de un fragmento principal y viendo un fragmento secundario duplicado. Intenté agregarlo en onStart del fragmento principal para poder acceder a la vista principal, que no está disponible en onCreate. Entonces, en lugar de mover el código a onCreate, lo moví a onActivityCreated; ese método tiene acceso a la vista primaria y también tiene acceso a la variable savedInstanceState para verificar si el fragmento ya se está agregando automáticamente. Esto no es un problema al agregar un fragmento de una actividad porque la vista de la actividad está disponible en onCreate.


Si por alguna razón es necesario agregar un fragmento de onStart u otro lugar donde savedInstanceState no está disponible, aquí es una alternativa. Uso del código original de inicio de la pregunta ...

if(mFragment == null) 
    { 
     mFragment = onCreatePane();  
     mFragment.setArguments(Utils.intentToFragmentArguments(getIntent())); 

     Log.w(TAG, "Fragment creation counter = " + createCounter); 
     createCounter++; 

     getSupportFragmentManager() 
     .beginTransaction() 
     .add(R.id.root_container,mFragment) 
     .commit(); 
    } 

...usted podría replace en lugar de add el fragmento:

if(mFragment == null) 
    { 
     mFragment = onCreatePane();  
     mFragment.setArguments(Utils.intentToFragmentArguments(getIntent())); 

     Log.w(TAG, "Fragment creation counter = " + createCounter); 
     createCounter++; 
    } 

    getSupportFragmentManager() 
    .beginTransaction() 
    .replace(R.id.root_container,mFragment) 
    .commit(); 

Entonces, si el fragmento ya fue añadido de forma automática, el nuevo fragmento se acaba de volver a colocarlo en la vista.

Cuestiones relacionadas