Comprender setRetainInstance (booleano) de Fragment
Empezando por la documentación:
setRetainInstance público vacío (retención booleana)
Controle si una instancia de fragmento se conserva durante la recreación de la actividad (por ejemplo, a partir de un cambio de configuración). Esto solo se puede usar con fragmentos que no están en la pila posterior. Si se establece, el ciclo de vida del fragmento será ligeramente diferente cuando se vuelva a crear una actividad:
- No se llamará a onDestroy() (pero sí se llamará a onDetach(), porque el fragmento se está separando de su actividad actual).
- No se llamará a onCreate(Bundle) ya que el fragmento no se está recreando.
- Se seguirán llamando a onAttach(Activity) y onActivityCreated(Bundle).
Tengo algunas preguntas:
¿El fragmento también conserva su vista o se recreará al cambiar la configuración? ¿Qué significa exactamente "retenido"?
¿Se destruirá el fragmento cuando el usuario abandone la actividad?
¿Por qué no funciona con fragmentos en la pila trasera?
¿Cuáles son los casos de uso en los que tiene sentido utilizar este método?
En primer lugar, consulte mi publicación sobre Fragmentos retenidos. Podría ayudar.
Ahora para responder a tus preguntas:
¿El fragmento también conserva su estado
de visualizacióno se recreará al cambiar la configuración? ¿Qué se "conserva" exactamente?
Sí, el Fragment
estado de se mantendrá durante el cambio de configuración. Específicamente, "retenido" significa que el fragmento no se destruirá con los cambios de configuración. Es decir, se Fragment
conservará incluso si el cambio de configuración provoca la destrucción del subyacenteActivity
.
¿Se destruirá el fragmento cuando el usuario abandone la actividad?
Al igual que Activity
s, Fragment
el sistema puede destruir s cuando los recursos de memoria son bajos. El hecho de que sus fragmentos conserven su estado de instancia a través de los cambios de configuración no tendrá ningún efecto sobre si el sistema los destruirá o no Fragment
una vez que abandone el archivo Activity
. Si abandona el Activity
(es decir, presionando el botón de inicio), Fragment
es posible que se destruya o no. Si abandonas el Activity
presionando el botón Atrás (llamando finish()
y destruyendo efectivamente el Activity
), todos los Activity
mensajes adjuntos Fragment
también serán destruidos.
¿Por qué no funciona con fragmentos en la pila trasera?
Probablemente haya varias razones por las que no es compatible, pero la razón más obvia para mí es que tiene Activity
una referencia a FragmentManager
y FragmentManager
administra el backstack. Es decir, no importa si elige conservar su Fragment
s o no, Activity
(y por lo tanto el FragmentManager
backstack de ) se destruirá en un cambio de configuración. Otra razón por la que podría no funcionar es porque las cosas podrían complicarse si se permitiera que tanto los fragmentos retenidos como los no retenidos existieran en el mismo backstack.
¿Cuáles son los casos de uso en los que tiene sentido utilizar este método?
Los fragmentos retenidos pueden ser muy útiles para propagar información de estado (especialmente la gestión de subprocesos) entre instancias de actividad. Por ejemplo, un fragmento puede servir como host para una instancia de Thread
o AsyncTask
, gestionando su funcionamiento. Consulte la publicación de mi blog sobre este tema para obtener más información.
En general, lo trataría de manera similar a usarlo onConfigurationChanged
con un Activity
... no lo use como una curita solo porque es demasiado vago para implementar/manejar un cambio de orientación correctamente. Úselo sólo cuando sea necesario.
setRetaininstance
solo es útil cuando se activity
destruye y se vuelve a crear debido a un cambio de configuración porque las instancias se guardan durante una llamada a onRetainNonConfigurationInstance
. Es decir, si gira el dispositivo, los fragmentos retenidos permanecerán allí (no se destruirán ni se recrearán), pero cuando el tiempo de ejecución finaliza la actividad para recuperar recursos, no queda nada. Cuando presionas el botón Atrás y sales de la actividad, todo se destruye.
Por lo general, uso esta función para guardar el tiempo de cambio de orientación. Digamos que descargué un montón de mapas de bits del servidor y cada uno tiene 1 MB, cuando el usuario gira accidentalmente su dispositivo, ciertamente no quiero volver a realizar todo el trabajo de descarga. Creo un Fragment
contenedor de mis mapas de bits, lo agrego al administrador y llamo setRetainInstance
, todos los mapas de bits siguen ahí incluso si cambia la orientación de la pantalla.
SetRetainInstance(true) permite que el fragmento sobreviva. Sus miembros se conservarán durante cambios de configuración como la rotación. Pero aún así se puede eliminar cuando la actividad se elimina en segundo plano. Si el sistema elimina la actividad que contiene en segundo plano, el sistema que manejó onSaveInstanceState debe guardar su estado de instancia correctamente. En otras palabras, siempre se llamará a onSaveInstanceState. Aunque no se llamará a onCreateView si SetRetainInstance es verdadero y el fragmento/actividad aún no se elimina, aún se llamará si se elimina y se intenta recuperarlo.
Aquí hay algunos análisis de la actividad/fragmento de Android, espero que ayude. http://ideaventure.blogspot.com.au/2014/01/android-activityfragment-life-cycle.html
setRetainInstance() - En desuso
Como fragmentos Versión 1.3.0-alpha01
El método setRetainInstance() en Fragmentos ha quedado obsoleto. Con la introducción de ViewModels, los desarrolladores tienen una API específica para retener el estado que se puede asociar con actividades, fragmentos y gráficos de navegación. Esto permite a los desarrolladores utilizar un Fragmento normal, no retenido, y mantener separado el estado específico que desean retener, evitando una fuente común de fugas y al mismo tiempo manteniendo las propiedades útiles de una única creación y destrucción del estado retenido (es decir, el constructor de ViewModel). y la devolución de llamada onCleared() que recibe).