Cuando se reemplaza un Fragmento y se coloca en la stack posterior (o se elimina), ¿permanece en la memoria?

¿Es el comportamiento similar a la forma en que funcionan las actividades? Por ejemplo, con Actividades, funciona así:

La actividad A inicia la actividad B , mientras que B está en la pantalla, el sistema puede eliminar A de la memoria si el sistema lo necesita. Al presionar BACK, A se volverá a crear en la memoria como si nunca hubiera salido en primer lugar.

He buscado una explicación clara de lo que sucede con la memoria con Fragmentos y no he encontrado nada. ¿Funciona de la misma manera? Por ejemplo:

La Actividad C tiene el Fragmento F en su diseño. Luego, en algún punto, F es reemplazado por el Fragmento G , pero F se mantiene en su stack posterior.

¿Permanecerá F en la memoria hasta que muera la C o el sistema la pueda eliminar según sea necesario?

Realmente, lo que estoy preguntando es si corro el riesgo de quedarme sin memoria si tengo una stack de Fragmentos complicados en una sola Actividad.

Eche un vistazo a esto: BackStackRecord.Op.fragment

Así es como se almacenan los fragmentos en la stack posterior. Tenga en cuenta que la referencia en vivo, ni WeakReference ni SoftReference se usan allí.

Ahora esto: FragmentManagerImpl.mBackStack

Ahí es donde el administrador almacena la stack de respaldo. Simple ArrayList , tampoco, WR o SR.

Y finalmente esto: Activity.mFragments

Esa es la referencia al administrador de fragmentos.

GC solo puede recostackr objetos que no tienen referencias en vivo (no son accesibles desde ningún hilo). Eso significa que hasta que se destruya tu Actividad (y, por lo tanto, la referencia de FragmentManager se haya ido), GC no podrá recoger ninguno de los Fragmentos en la stack de respaldo .

Tenga en cuenta que cuando la actividad se destruye y conserva el estado (como cuando se gira el dispositivo al modo horizontal), no retiene los objetos Fragment reales en la stack, solo sus estados – objetos Fragment.FragmentState , es decir, los fragmentos reales en la stack posterior son recreado cada vez que la actividad se vuelve a crear con estado retenido.

Espero que esto ayude.

PD Entonces, en resumen: Sí, puede quedarse sin memoria agregando Fragments a la stack trasera y agregando demasiadas vistas para ver la jerarquía.

UPD Teniendo en cuenta tu ejemplo, F permanecerá en la memoria hasta que C muera. Si C es asesinado y luego resucitado con una configuración diferente, F será destruido y reencarnado en un objeto diferente también. Entonces, la huella de memoria de F está alrededor hasta que C pierde el estado o se borra la stack de respaldo.

Lamento no poder proporcionarle alguna fuente de información oficial, pero también sentía curiosidad por ver qué sucedía y decidí probarlo. Y según mis pruebas, sí, corres el riesgo de quedarte sin memoria.

Tuve que agregar una cantidad increíble de Fragmentos (más de cien) en un bucle for para que ocurriera OutOfMemoryError , pero sucedió. Y al revisar mis registros, pude ver que los onCreate() y onCreateView() se llamaban muchas veces, pero onSaveInstance() , onPause() y onDestroy no se llamaban en absoluto.

Como referencia, así es como agregué los fragmentos a la backstack:

 getSupportFragmentManager().beginTransaction().add(R.id.scene_fragment_container, mSceneFragment).addToBackStack("FOOBAR").commit(); 

Y los Fragmentos que agregué fueron algo simples: un ImageView , un EditText , un par de TextViews , un SeekBar y un ListView .

Pero a menos que tenga una gran cantidad de datos en la memoria, no debería ser un problema.

Más tarde, intenté agregar solo 50 a la backstack, lo que causó la muerte de la aplicación y la reinicié. Y como esperaba / adiviné, todos los fragmentos se restauraron (y se onSaveInstance() los onSaveInstance() y onPause() ) así que la implementación de mi ciclo de vida no fue el problema que causó que OutOfMemoryError disparara.

De developer.android.com/guide/topics/fundamentals/fragments.html

Siempre se debe incrustar un fragmento en una actividad y el ciclo de vida del fragmento se ve directamente afectado por el ciclo de vida de la actividad del host. Por ejemplo, cuando la actividad está en pausa, también lo son todos los fragmentos, y cuando se destruye la actividad, también lo son todos los fragmentos. Sin embargo, mientras se está ejecutando una actividad (está en el estado reanudado del ciclo de vida), puede manipular cada fragmento de forma independiente, como agregarlos o eliminarlos. Cuando realiza una transacción de fragmento de este tipo, también puede agregarla a una stack de respaldo administrada por la actividad: cada entrada de la stack de respaldo en la actividad es un registro de la transacción de fragmento que ocurrió. La stack posterior le permite al usuario revertir una transacción de fragmento (navegar hacia atrás), presionando el botón ATRÁS.

Sí, puede quedarse sin memoria creando demasiados fragmentos en una sola actividad. Los fragmentos solo se destruirán cuando la Actividad que los contiene.