¿Cómo difieren las operaciones popBackStack () y replace ()?

He encontrado algún comportamiento curioso en mi aplicación al administrar Fragmentos y me preguntaba si podría ayudar a arrojar algo de luz sobre por qué sucede esto.

Tengo dos Fragmentos, los llamaremos Fragmento A y Fragmento B. El flujo general de mi aplicación es que cuando el usuario interactúa con el Fragmento A de alguna manera, el Fragmento B se muestra llamando a fragmentTransaction.replace() (esto sucede en todos los casos). Cuando muestro Fragmento B, agrego Fragmento A a la pila trasera; Entonces, cuando el usuario pulsa el botón de retroceso en el fragmento B, el fragmento A se muestra de nuevo saliendo de la pila trasera.

Eso es todo bien y bueno, pero hoy he descubierto que hay un flujo de Fragmento B que llama a fragmentTransaction.replace() , sustituyendo Fragmento B con la misma instancia del Fragmento A que está actualmente en la pila trasera.

En sí mismo no hay nada de malo en eso, sin embargo el comportamiento extraño surge cuando vuelvo del Fragmento A al Fragmento B. Si llamé fragmentTransaction.replace() , el método onCreate() del Fragmento B no se llama.

Sin embargo, si desplegaba el fragmento A de la pila posterior y luego lo reemplazaba con el fragmento B, el método onCreate() del fragmento B se disparaba. ¿Por qué es esto?

Tenga en cuenta que todas las instancias de Fragmento A y Fragmento B se crean en el momento en que se inicia su actividad de host.

Editar para aclarar. El caso en el que onCreate() se llama segunda vez es el siguiente: Fragmento A => reemplazar con Fragmento B, añadiendo el Fragmento A a la pila posterior => pop Fragmento A usando popBackStack() => reemplazar el Fragmento A con el Fragmento B de nuevo .

replace() hace 2 cosas:

  1. Eliminar el fragmento (A) actualmente añadido del contenedor (C) que indicó
  2. Añadir nuevo fragmento (B) al mismo contenedor

Estas 2 operaciones son lo que se guarda como un registro / transacción Backstack. Tenga en cuenta que el fragmento A permanece en estado created , y su vista se destruye.

Ahora popBackStack() invierte su última transacción que ha agregado a BackStack.

En este caso, esto sería 2 pasos:

  1. Quitar B de C
  2. Añadir de A a C

Después de esto, el fragmento B se detached , y si no guardó referencias a él, será recolectado de basura.

Para responder la primera parte de su pregunta, no hay ninguna llamada onCreate() , porque FragmentB permaneció en estado created . Y la respuesta a la segunda parte de la pregunta es un poco más larga.

Primero, es importante entender que en realidad no agregas Fragments a Backstack, agregas FragmentTransactions . Por lo tanto, cuando piensa que "reemplazar con el fragmento B, añadiendo el fragmento A a la pila trasera", que realmente añadir toda esta operación a backstack – que es la sustitución de A con B. Este reemplazo consiste en 2 acciones – eliminar A y agregar B .

A continuación, el siguiente paso es hacer estallar la transacción que contiene este reemplazo. Así que no estás haciendo estallar FragmentA, estás invirtiendo "quitar A, añadir B", que se invierte es "quitar B, añadir A".

Y entonces el paso final debe ser más claro – no hay B que FragmentManager es consciente de, por lo que cuando se agrega sustituyendo A con B en su último paso, B tiene que pasar por sus métodos de ciclo de vida temprano – onAttach() y onCreate() .

El siguiente código ilustra lo que está sucediendo.

 FragmentManager fm = getFragmentManager(); FragmentA fragmentA = new FragmentA(); FragmentB fragmentB = new FragmentB(); // 1. Show A fm.beginTransaction() .add(fragmentA, R.id.container) .commit(); // 2. Replace A with B // FragmentManager keeps reference to fragmentA; // it stays attached and created; fragmentB goes // through lifecycle methods onAttach(), onCreate() // and so on. fm.beginTransaction() .replace(fragmentB, R.id.container) .addToBackstack(null) .commit(); // 2'. Alternative to replace() method fm.beginTransaction() .remove(fragmentA) .add(fragmentB, R.id.container) .addToBackstack(null) .commit(); // 3. Reverse (2); Result - A is visible // What happens: // 1) fragmentB is removed from container, it is detached now; // FragmentManager doesn't keep reference to it anymore // 2) Instance of FragmentA is placed back in the container // Now your Backstack is empty, FragmentManager is aware only // of FragmentA instance fm.popBackStack(); // 4. Show B // Since fragmentB was detached, it goes through its early // lifecycle methods: onAttach() and onCreate(). fm.beginTransaction() .replace(fragmentB, R.id.container) .addToBackstack(null) .commit(); 

Esto es quizás porque el administrador de fragmentos reutilizar la instancia de fragmento en lugar de recrearlo. Si el código dentro del fragmento B onCreate() requiere ser ejecutado cuando se muestra el fragmento, mueva el código en otro método como onResume() .

  • Actualización de la hora y la fecha por segundo en Android
  • Desempeño de Android: "Evita los internos y los setters"
  • ¿Cómo publicar pares clave / valor con una subida de archivo en android
  • Cómo cambiar la opacidad de un mapa de bits?
  • Reemplazar cada palabra con etiqueta
  • Cómo extraer el cursor y el valor entero de una matriz de clase Object
  • Cuando se procesa una cadena csv con un campo final vacío, myString.split (",") devuelve un número incorrecto de entradas de matriz
  • ¿Cómo puedo contestar una llamada telefónica y colgarla?
  • Cómo poner elementos anidados de archivo XML a la lista de objetos con VTD-XML parser?
  • Importación de la biblioteca de Facebook en Android Studio: No se pudo encontrar la propiedad 'ANDROID_BUILD_SDK_VERSION'
  • Volver a escribir el código Java a JS - la creación de un audio de bytes?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.