¿Los fragmentos con setRetainInstance (true) sobreviven al cierre del proceso?

Teniendo en cuenta este escenario: Si he creado una actividad y se mueve al fondo y esta actividad contiene un Fragment que se establece en setRetainInstance(true) , el sistema operativo Android podría en algún momento todavía decidir cerrar el proceso de alojamiento de la actividad con el fin de liberar memoria.

Entonces el estado de la Activity se guarda vía onSaveInstanceState(Bundle) donde – por lo que entendí – el Bundle relacionado está escrito y al sistema de archivos para sobrevivir el proceso cerrado. (Por lo tanto el requisito de que los objetos del paquete sean Serializable ). Posteriormente, el estado de las aplicaciones se puede recuperar en un nuevo proceso a través de onRestoreInstanceState(Bundle) .

En contraste, mi Fragment se permite contener variables que no son necesariamente Serializable . Por lo tanto, pensé, el Fragment no se puede almacenar en el disco como el Bundle es. Entonces, ¿qué sucede con mi fragmento cuando el proceso es asesinado?

Me preguntaba sobre esta lectura de la guía del desarrollador ( http://developer.android.com/guide/components/processes-and-threads.html ):

Un proceso que contiene una actividad que no está visible para el usuario (se ha llamado el método onStop () de la actividad). Estos procesos no tienen un impacto directo en la experiencia del usuario, y el sistema puede matarlos en cualquier momento para recuperar la memoria de un proceso de primer plano, visible o de servicio. Por lo general, hay muchos procesos de fondo en ejecución, por lo que se mantienen en una lista LRU (menos utilizado recientemente) para asegurarse de que el proceso con la actividad que fue vista más recientemente por el usuario es el último a ser matado. Si una actividad implementa correctamente sus métodos de ciclo de vida y guarda su estado actual , eliminar su proceso no tendrá un efecto visible en la experiencia del usuario, ya que cuando el usuario vuelve a la actividad, la actividad restaura todo su estado visible.

Entendí el asesinato anterior de tal manera que la instancia VM se cierra y el estado del proceso se escribe en el sistema de archivos (aquí viene el Bundle en juego). Más adelante se leen los paquetes para reanudar el proceso. Dado que la retención de fragmentos no se refiere a los métodos de ciclo de vida y ya que no sabría cómo mantener, por ejemplo, un puntero a una conexión de red (por supuesto, nunca debe tener un puntero en un fragmento de todos modos), me preguntaba si los fragmentos Se siguen restaurando si el proceso se cierra mientras tanto. Llegué a la conclusión de que seguramente necesitaban ser recreados y que por lo tanto los métodos del ciclo de vida deben ser preferidos sobre setRetainInstance(true) siempre que sea posible.

¿Tiene sentido esta suposición?

Suena como si estuvieras mezclando dos conceptos aquí.

  • Guardar el estado en los cambios de configuración no implica la serialización. Si solicita setRetainInstance() para un Fragment , significa que permanecerá totalmente en la memoria y no volverá a crearse sólo para los cambios de configuración. Un mecanismo similar está disponible para objetos de Activity , pero necesitan definir explícitamente un Object que se va a guardar. Esto funciona a través de Activity.onRetainNonConfigurationInstance() , no a través de onSaveInstanceStae() .
  • El otro mecanismo implica serialización y posiblemente (quizás no siempre, no seguro) sistema de archivos E / S para poder reproducir información de estado incluso si una Activity / Fragment es destruida (lo cual ocurre independientemente de su Process alojamiento, btw). Esto funciona a través de Activity.onSaveInstanceState() y Fragment.onSaveInstanceState() .
  • Por supuesto, puede utilizar el segundo mecanismo con el fin de la primera, lo que ralentiza la forma en que su aplicación se ocupa de los cambios de configuración. Dependiendo de su estado interno, la desaceleración podría ser marginal de significativo.

Con respecto a sus preguntas.

  • "Mi Fragmento en contraste, se le permite contener variables que no son serializable." Bueno, lo mismo es cierto para su Activity . Puede contener objetos no serializables que se pueden guardar a través de los cambios de configuración como se describió anteriormente.
  • "El fragmento no se puede almacenar en el disco cuando se cierra un proceso y debe ser recreado cuando se restauró una actividad". No, ambos mecanismos están disponibles para ambos tipos de objetos.

Espero poder contribuir a aclarar esto un poco.

Editar después de su primer comentario.

Respecto al comentario:

  • " onRetainNonConfigurationInstance está obsoleta": Sí. Lo mencioné con fines de demostración debido a una formulación específica en su pregunta. Además, con los dispositivos Android 2 con un 46% de cuota de mercado de hoy (cifras oficiales de Google), este método se quedará definitivamente por mucho tiempo, obsoleto o no.
  • "Mi principal preocupación es acerca de lo que sucederá con la instancia de fragmento cuando mi proceso de alojamiento sea eliminado y eliminado de la memoria": su instancia de fragmento se eliminará de la memoria y, por supuesto, no hay forma de que se restaure como está con su completo Automáticamente . Esto sólo se hace cuando se establece setRetainInstanceState en el caso de cambios de configuración. (Pero tenga en cuenta que esto se refiere a la instancia , en otras palabras, el objeto completo.)

Con respecto a su edición:

  • Una vez más, , tu Fragment será almacenado y restaurado en / desde el Bundle sin importar setRetainInstanceState si usas Fragment.onSaveInstanceState() para este propósito, para todo lo que tenga sentido.
  • No es cierto que "todo su estado visible" se guardará como el texto que se refiere a las reclamaciones; Por ejemplo, el atributo de visibility no se guardará. Si eso se supone que es un error o una característica que no sé, pero es un hecho . Pero esto es sólo una observación de lado; Los elementos de la interfaz de usuario guardarán la mayor parte de su estado relevante.
  • "El estado del proceso se escribe en el sistema de archivos": No! El estado de los objetos que son capaces de guardar su estado en un Bundle y de implementar realmente guardar su estado se guardará en un Bundle , esto significa que debe proporcionar dicha información usted mismo si desea que su Fragment guarde información de estado. También, nuevamente: No , esto no sólo se relaciona con matar el proceso sino también con la eliminación de objetos de Activity y Fragment que no son visibles; Como la última Actividad mostrada – el Process puede permanecer vivo.
  • "Se leerán los paquetes para reanudar el proceso": No, se leerá el Bundle para pasarlo a la reconstrucción de los objetos Actividad y / o Fragmento , no se hace nada automáticamente en este proceso (excepto los objetos de biblioteca que guardan su estado también Restaurar su estado), pero Android no "reanudar" el "Proceso" de estos Bundle .
  • "Dado que la retención de fragmentos no se refiere a los métodos del ciclo de vida": Una vez más, creo que está mezclando los dos conceptos. La "retención" de un Fragment sólo se realiza en los cambios de configuración _IF_ que se solicita a través de setRetainInstance , pero estamos hablando sobre la recreación de objetos Fragment de un Bundle aquí, que implica los métodos de ciclo de vida documentados por Google .
  • "No sabría cómo conservar, por ejemplo, un puntero a una conexión de red": Una vez más, esta debe ser una declaración basada en su confusión. Por supuesto, puede mantener una referencia a una conexión de red tras el cambio de configuración (como se solicita por setRetainInstance ), porque cuando eso sucede, todo se guarda simplemente en la memoria. Además, incluso si su Fragment se elimina (porque se hizo invisible) y su proceso sigue ahí (porque muestra la siguiente Actividad), puede (y debe) mantener referencias a objetos que son costosos de volver a crear, como un Conexión de red, en su objeto de Application , que existe mientras su proceso vive (más o menos). Solo cuando su aplicación completa es asesinada por Android, se pierde todo, pero la serialización que estamos discutiendo ocurre mucho más a menudo .

Su conclusión:

Llegué a la conclusión de que seguramente necesitaban ser recreados y que por lo tanto los métodos del ciclo de vida deben ser preferidos sobre setRetainInstance (true) siempre que sea posible. ¿Tiene sentido esta suposición?

Desafortunadamente no, ya que están mezclando conceptos completamente independientes.

Voy a darle un intento final:

  • Desea mantener una referencia de conexión de red que necesite en toda la aplicación en su objeto de Application ya que sería una pésima experiencia de usuario si la creó desde cero de forma regular en toda la aplicación.
  • Su objeto de Application sólo fallecerá si Android mata su aplicación.
  • Tus objetos Activity y Fragment se eliminarán de tu aplicación regularmente cuando el usuario avance dentro de tu aplicación.
  • Cuando el usuario presiona "atrás", Android volverá a crear objetos de Activity y Fragment del Bundle usando métodos de ciclo de vida. Guardar algo en un Bundle tiene sentido si tiene costosos cálculos que hacer para volver a crear el estado interno. Usted puede vivir sin el mecanismo Bundle porque Android siempre guardar el Intent por lo que si no haces nada, entonces comenzará sin estado guardado.
  • Cuando se produce un cambio de configuración, Android le permite optimizar la experiencia del usuario manteniendo objetos en la memoria a través del cambio de configuración. Aquí, los métodos del ciclo de vida de la Activity se involved y es hasta su puesta en práctica para utilizar los datos ahorrados con eficacia. Para Fragment s, aquí es donde setRetainInstance' comes into play: Your Fragment` sobrevivirá al cambio de configuración en la memoria si lo configura.
FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.