Android: variable estática nula en memoria baja

Tengo una aplicación que tiene algunas variables estáticas. Estas variables se almacenan en una Clase independiente llamada DataContext. Estas variables se inicializan desde archivos sin formato al inicio de la aplicación (se llama a un método llamado DataContext.initConstant () en onCreate () de MyApplication que extiende la aplicación).

(EDITAR: el método initConstant utiliza una AsyncTask para cargar estos datos de los archivos).

Cuando mi aplicación pasa al segundo plano durante un tiempo determinado o cuando mi aplicación utilizaba mucha memoria, estas variables estáticas se vuelven nulas.

  1. ¿Cómo puede ser prevenido?

  2. Si no, ¿qué debería hacer con mis variables estáticas?

    Tengo otros datos que se almacenan en variables estáticas para usar en diferentes actividades, pero los onLowMemory() o los paso a null en onLowMemory() de MyApplication.

  3. ¿Cuál es la mejor manera de mantener algunos datos accesibles entre actividades si estos datos son demasiado grandes para ser serializados en un Intento, una base de datos no puede ser utilizada (por el motivo que sea) y tampoco puede almacenarse en archivos mediante serialización?

Lo más probable es que su aplicación esté siendo eliminada mientras está en segundo plano, y luego se vuelva a crear cuando regrese a ella. Consulte la documentación del ciclo de vida de la actividad sobre cuándo podría ocurrir esto para una sola actividad. Debe asegurarse de mover todo lo almacenado en la memoria a un almacenamiento más permanente en el momento correcto para evitar perder esa información si la aplicación se destruye.

No estoy seguro de qué es exactamente lo que está almacenando, pero parece que el uso de Preferencias compartidas podría funcionar bien. Esta página sobre Almacenamiento de datos explica una serie de maneras diferentes de almacenar datos de forma más permanente, incluidas las Preferencias compartidas.

  1. No puedes. Android necesita liberar memoria de vez en cuando. Imagínese si todas las aplicaciones tuvieran una tonelada de datos estáticos que se supone que deberían residir para siempre. ¿Cómo encajaría eso en la memoria? Es un teléfono móvil. No tiene memoria virtual.

  2. (y 3): todo lo que se pretende que sea persistente debe almacenarse, ya sea a través de SharedPreferences, una base de datos Sqlite o un archivo.

Si no estuviera usando archivos sin procesar, le aconsejo que se inicialice cuando se cargue la clase.

Por ejemplo,

 public static Map< ?,?> myStaticMap = new HashMap< ?,?>(); static { //fill myStaticMap } 

Tienes algunas preocupaciones más grandes de las que preocuparte si estás cargando archivos de esa manera. Por ejemplo, ¿qué pasa con los errores de E / S o los problemas de latencia? Recibirá advertencias en gingerbread (si las habilita) para hacer E / S en su hilo principal. Tal vez debería tener un objeto para recuperar estos valores en lugar de una clase con campos estáticos. (quizás con un caché estático, aunque debe sincronizarlo antes de comprobarlo / cambiarlo)

Supongo que este es un problema de caché de datos.

No se garantiza el almacenamiento de datos en clases estáticas cuando el usuario intercambia aplicaciones a menudo. El sistema Android recuperará cualquier actividad de fondo cuando la memoria es baja. La clase estática está definitivamente entre esta categoría.

La forma correcta de hacerlo es usar sharedPreference para conservar los datos de caché.

Puede crear su propio getter y setter de los datos que desee y envolverlo en el objeto sharedPreference. Cuando accede usando getter, siempre debe verificar si el valor está vacío o caducado. Puede almacenar un update_time cuando usa setter.

Para datos específicos de la actividad, puede usar getPreference(permission) , si desea compartir datos entre actividades y otros componentes de las aplicaciones, puede usar getSharedPreference(name, permission) .

Normalmente, el permiso será MODE_PRIVATE de modo que solo se pueda acceder a los datos dentro de su aplicación.

Debe agrupar los datos y almacenar en la diferencia el objeto sharedPreference. Esta es una buena práctica porque cuando quieres invalidar ese grupo de datos, solo se trata de un trazador de líneas.

editor.clear(); editor.commit()

Si desea almacenar en caché un objeto complejo, debe serializarlo. Prefiero el formato JSON. Entonces necesitas algún mecanismo de conversión en su lugar. Para hacer esto, crearé mi clase de objeto de datos extendiendo la clase JSONable. La clase JSONable tendrá el toJSON() y readFromJSON() . Esto es conveniente cuando restaura y serializa datos.

Guardo un objeto User y un objeto Client en mi scope estático. He notado que de vez en cuando la referencia se vuelve nula. Así que ahora en mis getters verifico si este valor es nulo y si es así reinicio la aplicación.

 Intent i = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName()); i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); context.startActivity(i); 

También podría haber elegido volver a cargar el Cliente porque almaceno el Token de Acceso en las preferencias, sin embargo, hago tanta inicialización que decidí que reiniciar la aplicación sería la mejor idea.

En su método onResume() , puede consultar los datos estáticos para ver si están presentes y, de no ser así, volver a cargarlos.

En lugar de usar la variable estática, puede usar la preferencia compartida para almacenar el valor.

Nota: para las preferencias compartidas, tampoco debe dar mucha carga.

He resuelto este problema al tener la superclase con función getter y setter para almacenar y recuperar variables de preferencias compartidas.

Toda la clase de mi aplicación extendió la súper clase en lugar de la actividad.