Ciclo de vida de objetos estáticos de Android

101

Estoy creando una aplicación de búsqueda de eventos, establecemos los criterios de búsqueda desde una pantalla y luego el usuario puede editar los criterios de búsqueda desde la tercera pantalla y pasar a la cuarta pantalla.

Para lograr la tarea anterior, estoy usando un objeto estático que recuerda los valores alrededor de la aplicación y no necesito hacer nada adicional.

Pero me temo que si sobre el ciclo de vida de los objetos estáticos en Android, si se encuentra poca memoria, ¿eliminar los objetos estáticos de Android?

Como Android es compatible con la multitarea, si el usuario cambia a otra aplicación y cuando el usuario vuelve, la aplicación comienza a actuar como un loco, ¿el objeto estático se elimina cuando es multitarea? alguna idea ?? ¿Y también sugiero que sostener un objeto estático a través del método singleton es un mejor enfoque?

d-man
fuente

Respuestas:

238

Comencemos con un poco de antecedentes: ¿Qué sucede cuando inicia una aplicación?
El SO inicia un proceso y le asigna un ID de proceso único y asigna una tabla de proceso. Un proceso inicia una instancia de DVM (Dalvik VM); Cada aplicación se ejecuta dentro de un DVM.
Un DVM gestiona la descarga de carga de clases, el ciclo de vida de la instancia, GC, etc.

Duración de una variable estática: una variable estática surge cuando la JVM carga una clase y muere cuando la clase se descarga.

Entonces, si crea una aplicación de Android e inicializa una variable estática, permanecerá en la JVM hasta que ocurra una de las siguientes situaciones:
1. la clase se descarga
2. la JVM se apaga
3. el proceso muere

Tenga en cuenta que el valor de la variable estática persistirá cuando cambie a una actividad diferente de otra aplicación y no ocurra ninguna de las tres anteriores. Si ocurre alguno de los tres anteriores, la estática perderá su valor.

Puede probar esto con algunas líneas de código:

  1. imprima la estática no inicializada en onCreate de su actividad -> debería imprimir nulo
  2. inicializar la estática. imprimirlo -> el valor no sería nulo
  3. Presiona el botón Atrás y ve a la pantalla de inicio. Nota: la pantalla de inicio es otra actividad.
  4. Inicie su actividad nuevamente -> la variable estática no será nula
  5. Elimine su proceso de solicitud desde DDMS (botón de parada en la ventana de dispositivos).
  6. Reinicie su actividad -> la estática tendrá un valor nulo.

Espero que ayude.

Samuh
fuente
1
Quiero saber por qué pierdo el valor de mi campo en el objeto de la aplicación si no es estático cuando comienzo una nueva actividad, por ejemplo, declaro la página actual variable en el objeto de la aplicación y su valor siempre vuelve a cero cuando abro una nueva actividad
Mohammed Subhi Sheikh Quroush
cuando llamo a super.onRestoreInstanceState (SavedInstanceState); Pierdo mi variable incluso si son estáticas, ¿cuál es el problema?
Mohammed Subhi Sheikh Quroush
1
esta es una buena explicación (por lo que no -1) pero es un poco intrascendente: el OP preguntó explícitamente sobre "situaciones de poca memoria" (la misma razón por la que estoy aquí), donde hasta donde yo sé, los OS podrían matar la VM y reinícielo más tarde con los mismos parámetros, y este caso ( SI es algo real) no está cubierto aquí ...
Rick77
1
@suitianshi Creo que podemos inicializar instancias estáticas en Application.onCreate, porque incluso si nuestra aplicación pasa a segundo plano y el proceso se mata, tan pronto como volvamos a nuestra aplicación, la clase de aplicación se instanciará y llamará a sus métodos de ciclo de vida correspondientes ¡de nuevo! aunque necesito confirmación sobre esto, me pregunto si podría haber algún escenario en el que la instancia estática inicializada en Application.onCreate pierda su valor.
Sarthak Mittal
1
Lo que me falta aquí es una explicación para "1. la clase está descargada". ¿Cuándo sucedería esto? ¿JVM descargaría una clase si se está quedando sin memoria?
stoefln
16

Bueno, el patrón Singleton también se basa en el uso de variables estáticas, por lo que en realidad estaría en la misma posición. Si bien el enfoque estático puede funcionar la mayoría de las veces, puede suceder que, en algunos casos, cuando la memoria está llena y otra actividad toma el primer plano antes de que su aplicación se mueva a la siguiente pantalla, el proceso de su actividad podría terminar y perder los valores estáticos. Sin embargo, Android ofrece algunas opciones para mantener valores entre estados o transmitirlos, como:

  • utilizando un Intent, puede pasar sus criterios de búsqueda de una actividad a otra (similar a una solicitud http web)
  • utilizando las preferencias de la aplicación, puede guardar los valores y recuperarlos en la actividad que los necesite
  • utilizando la base de datos sqlite, puede conservarlos en una tabla y recuperarlos más tarde
  • Si solo necesita guardar el estado de la actividad para que, al reiniciar, los campos se llenen con sus valores previamente seleccionados, puede implementar el método de actividad onSaveInstanceState (); tenga en cuenta que esto no se recomienda para la persistencia de estados entre actividades.

Puede obtener algunos ejemplos de código del uso de preferencias, intenciones y la base de datos sqlite mirando el árbol de código fuente de aegis-shield en el código de Google o en otras aplicaciones de Android de código abierto.

r1k0
fuente
6

Después de investigar un poco, resulta que usar la aplicación para almacenar singleton no es una gran idea, a menos que esté listo para recrearla:

No almacene datos en el objeto de la aplicación

por lo que, si bien la respuesta aceptada es técnicamente correcta, no proporciona toda la información.

Como sugiere el enlace anterior, si realmente desea seguir con ese modelo, debe estar listo para verificar si hay nulos y volver a crear los datos, si es posible.

Rick77
fuente
3

@ r1k0 está aquí. El almacenamiento de datos en los campos estáticos de una clase no persistirá por sí solo en los procesos de aplicación mata y reinicia. Android mata de forma rutinaria los procesos (aplicaciones en ejecución) cuando necesita memoria.

Según el documento de Android: estado de actividad y expulsión de la memoria ,

El sistema nunca mata una actividad directamente. En cambio, mata el proceso en el que se ejecuta la actividad, destruyendo no solo la actividad sino también todo lo demás que se ejecuta en el proceso.

Puede guardar y restaurar el estado de primitivas, así como de objetos serializables y parcelables utilizando los métodos siguientes. Estos se llaman automáticamente durante el ciclo de vida normal de la actividad.

protected void onSaveInstanceState(Bundle state) {}
protected void onRestoreInstanceState(Bundle savedInstanceState){}

Entonces, si tiene una clase que solo tiene variables estáticas, puede guardar el estado de cada campo en onSaveInstanceState () y restaurarlos en onRestoreInstanceState (). Cuando Android mata el proceso en el que se ejecuta su aplicación, el estado de sus variables se guardará, y cuando Android restaure su aplicación, los valores se restaurarán en la memoria en el mismo estado que antes.

eric.mcgregor
fuente