44

estado buscando para este problema por un tiempo en vano ahora:Cómo determinar fragmento restaurado de backstack

cómo determinar fragmento se ha restaurado de backstack? Estoy usando la biblioteca de compatibilidad y un ListFragment dentro de una FragmentActivity. Cuando se selecciona un elemento dentro de ListFragment, se inicia un nuevo Fragment para reemplazar el ListFragment.

Me di cuenta de que cuando FragmentActivity se detiene, se llama al onSaveInstanceState del Fragmento. Pero cuando el Fragmento se coloca en la pila posterior a través de FragmentTransaction, onSaveInstanceState no se llama, entonces los métodos del ciclo de vida onCreateView y onActivityCreated se invocan con el paquete null savedInstanceState Bundle.

Lo estoy preguntando porque quiero cargar algunos datos cuando se crea o restaura el fragmento, pero no cuando el usuario vuelve a través de. pila posterior.

He visto How to check if Fragment was restored from a backstack? pero quiero agregar más detalles con la esperanza de que esto incite una respuesta.

Editar: di cuenta http://developer.android.com/reference/android/app/Fragment.html#onSaveInstanceState(android.os.Bundle) dice

Nota sin embargo: este método puede ser llamado en cualquier momento antes OnDestroy(). Hay muchas situaciones en las que un fragmento se puede derribar (como cuando se coloca en la pila posterior sin UI), pero su estado no se guardará hasta que su actividad propietaria realmente necesite guardar su estado.

Así onSaveInstanceState es definitivamente fuera de la cuestión ...

+0

Como una pequeña actualización a esta pregunta, estoy sospechando cada vez más que se debe a las peculiaridades de la biblioteca de compatibilidad. Aún no he intentado ejecutar un caso de prueba en dispositivos más de 3,0, lo comprobaré cuando lo haga. – dvd

+0

por qué no realiza su llamada al servidor para cargar los datos en 'onCreate()'. Quizás, eso aliviará tus problemas. Creo que este método en particular no se llama cuando un fragmento se restaura desde la pila de respaldo. – Abhijit

Respuesta

34

creo que la mayoría forma sencilla es hacer esto por ejemplo en onViewCreated() Método:

if (savedInstanceState == null && !mAlreadyLoaded) { 
    mAlreadyLoaded = true; 

    // Do this code only first time, not after rotation or reuse fragment from backstack 
} 

Porque cuando fragmento de poner Android en backstack, sólo destruir su punto de vista, pero no matan a instancia propia, así que mAlreadyLoaded seguirá siendo cierto cuando el fragmento se restaure desde backstack.

+0

Esta es la respuesta correcta para determinar si la instancia del fragmento se restauró de la pila posterior. Finalmente tuve la oportunidad de volver a visitar este tema y leer la fuente de FragmentManager en la biblioteca de soporte v4 versión 13. La instancia de fragmento como ATom dijo se mantiene cuando se agrega a la pila de respaldo. Entonces, establecer y verificar una bandera en onViewCreated funciona. – dvd

+5

Esto solo funciona si llamaste a 'setRetainInstance (true)', que no siempre es una opción. –

+1

@BenoitDuffez Creo que solo es necesario si estás trabajando con un 'Fragmento' cuyo' FragmentTransaction' no se agregó a la pila posterior. Si la transacción se agregó a la pila posterior, ese 'Fragmento' se retendrá automáticamente (es decir, no se llamará a su' onDestroy'). [** De los documentos **] (http://developer.android.com/guide/components/fragments.html#Transactions). Si no lo agrega a la pila posterior, tendrá que llamar a 'setRetainInstance()' como dijo si desea que no se destruya. –

30
getSupportFragmentManager().addOnBackStackChangedListener(new OnBackStackChangedListener() {  
      public void onBackStackChanged() { 
       Log.i(TAG, "back stack changed "); 
       int backCount = getSupportFragmentManager().getBackStackEntryCount(); 
       if (backCount == 0){ 
            // block where back has been pressed. since backstack is zero. 
       } 
      } 
     }); 

uso de este addOnBackStackChangedListener.

+4

Acabo de probar esto, el problema es onBackStackChanged se llama después de llamar a los métodos de ciclo de vida del fragmento. Lo que quiero hacer es: cargar datos cuando se crea el fragmento por primera vez, almacenar datos y restaurar cuando sea necesario (sin recargar). Eso se logró con la carga/restauración condicional en onActivityCreated. Cuando el fragmento se restablece haciendo estallar la pila posterior, no vuelva a cargar los datos. Incluso si configuro un indicador en onBackStackChanged, los métodos del ciclo de vida no lo verán. – dvd

+0

¡Funciona como un encanto! – portfoliobuilder

+0

question.acceptedAnswer = this; – satheeshwaran

0

En algunos casos, puede utilizar el método isVisible para entender si es la primera vez que se muestra un fragmento o si se restaura desde la pila posterior.

8

edición mayor: 15 Oct 2013

La explicación anterior (mantenido a continuación como referencia) falla cuando la aplicación se pone a un segundo plano y la trajo de vuelta al primer plano.

En su lugar, es mejor comparar el tamaño actual de la backstack con el que se creó cuando se creó & en la backstack.


tomar un buen vistazo a la figura 2 en http://developer.android.com/guide/components/fragments.html#Creating

¿Qué le dice a esta figura que es que cuando un fragmento se restaura desde el backstack, su onCreate() no se llama, mientras que su onCreateView() es.


Por lo tanto, es posible que desee hacer algo como esto:

public class MyFragment extends Fragment { 
    int mBackStackSize = 0; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     mBackStackSize = getFragmentManager().getBackStackEntryCount(); 
    } 

    public boolean isRestoredFromBackstack() { 
     return mBackStackSize > getFragmentManager().getBackStackEntryCount(); 
    } 
} 
4

Si ha añadido fragmento de backstack, y después de alguna manipulación que ocultarlo usando fragmentTransaction.hide (fragmento) y luego restaurar desde backstack como fragmentTransaction.show (fragmentManager.findFragmentByTag (fragment.getName())); puede anular onHiddenChanged (booleano oculta)

@Override 
public void onHiddenChanged(boolean hidden) { 
    // TODO Auto-generated method stub 
    super.onHiddenChanged(hidden); 
    if (!hidden) { 
     //fragment became visible 
     //your code here 
    } 
} 
+0

Eso es exactamente lo que estaba buscando. ¡Gracias! Solo tenga en cuenta que debe ser 'if (! Hidden) {' – crubio

0
Fragment.getFragmentManager() == null 

antes y después de estallar añadido

12

Cuando un fragmento va a back-pila onDestroyView() llamada. No onDestroy().

Y cuando aparece un fragmento de la pila posterior onCreateView() llamado. No onCreate().

por lo que añadir un boolean mIsRestoredFromBackstack para fragmentar y siguen a continuación:

@Override 
public void onCreate(Bundle savedInstanceState) 
{ 
    super.onCreate(savedInstanceState); 
    mIsRestoredFromBackstack = false; 
} 

@Override 
public void onResume() 
{ 
    super.onResume(); 
    if(mIsRestoredFromBackstack) 
    { 
     // The fragment restored from backstack, do some work here! 
    } 
} 

@Override 
public void onDestroyView() 
{ 
    super.onDestroyView(); 
    mIsRestoredFromBackstack = true; 
} 
+0

onDestroyView se llama desde el bloqueo de la pantalla, por lo que mi acción se invoca dos veces después de volver desde backstack – ldrrp

+1

Funciona. Gracias por responder. –

Cuestiones relacionadas