2010-11-07 21 views
16

Tengo una memoria caché de imagen en mi aplicación que se implementa mediante SoftReferences. Dalvik inicia aplicaciones con un montón relativamente pequeño, y luego lo aumenta en caso de demanda. Pero me gustaría que mi tamaño sea más grande desde el principio. Esto se debe a que cuando ya tengo algunas imágenes en la memoria caché y comienza una actividad (por ejemplo) u otra demanda máxima de memoria ocurre, mi caché se purga para permitir la memoria para esa demanda máxima. Como resultado, después de que se acabe el pico, aún tengo 2-3 MB de espacio libre pero mi caché está vacía.Android: ¿cómo aumentar el tamaño del montón en tiempo de ejecución?

La solución que veo para este problema es preasignar un golpe de derecha más grande así que incluso con el pico de consumo de 2-3 MB todavía tiene espacio para que mis SoftReferences no se purguen.

Encontré que VMRuntime.getRuntime().setMinimumHeapSize(BIGGER_SIZE) sería útil. En particular, Google usa eso en sus aplicaciones, como se menciona here. Sin embargo, la clase VMRuntime está marcada como obsoleta y se dice que se eliminará de la API pública en una versión futura. Entonces setMinimumHeapSize no es una solución permanente.

¿Cómo haré que Dalvik crezca en el arranque?

Actualmente utilizo una técnica realmente directa y cursi con solo asignar una gran matriz y soltarla. Esto hace que Dalvik crezca como yo quiera. Sin embargo, estoy seguro de que debe haber una forma más elegante de hacerlo. ¿Podrías decirme eso, por favor?

+1

dudo encontrará una manera de hacer esto utilizando las API públicas – Falmarri

+0

mapas de Google utiliza la reflexión y esta API, me encontré con este post mientras buscaba información sobre la llamada :) – sherpya

Respuesta

6

En lugar de aumentar el tamaño del montón, puede hacer algo mejor. Como dijiste, estás manteniendo el caché en tu aplicación que se implementa mediante SoftReferences. Lo mejor es usar LRUCache que puede hacer algo como esto:

private LruCache<String, Bitmap> bitmapCache; 
final int memClass; 
int cacheSize; 

memClass = ((ActivityManager) context.getSystemService(
    Context.ACTIVITY_SERVICE)).getMemoryClass(); 

Volver al aproximada clase de memoria por aplicación del dispositivo actual. Esto le da una idea de qué tan difícil es el límite de memoria que debe imponer a su aplicación para que el sistema en general funcione mejor. El valor devuelto está en megabytes; la clase de memoria básica de Android es 16 (que es el límite de almacenamiento Java de esos dispositivos); algunos dispositivos con más memoria pueden devolver 24 o incluso más.

cacheSize = 1024 * 1024 * memClass/10; 
bitmapCache = new LruCache<String, Bitmap>(cacheSize) { 
    @Override 
    protected int sizeOf(String key, Bitmap value) { 
    return value.getHeight() * value.getRowBytes(); 
} 
}; 

que eliminará las imágenes de mapa de bits de LRUCache si la memoria excede la memoria situada a LRUCache y cargar la nueva imagen en ella.

0

No creo que se pueda o se supone que influya en la memoria de un dispositivo en este nivel. Deje que el sistema haga lo suyo y no vaya en contra de eso. ¿Necesita mantener un caché de imágenes tan grande con SoftReferences incluso cuando comienzan las actividades?

¿Quieres comprobar cómo se hace en estantes: véase la línea 82 en http://code.google.com/p/shelves/source/browse/trunk/Shelves/src/org/curiouscreature/android/shelves/util/ImageUtilities.java?r=26

+1

Nunca dije mi caché es grande. De hecho, no depende del tamaño de la memoria caché, incluso con cachés pequeños no funcionará, como ya he dicho, debido a esas sobrecargas de memoria. Tengo un caché de ~ 100 elementos de 2 a 3 KB cada uno, eso no es una gran caché, pero aún así se borra todo el tiempo. Descubrí que el recolector de basura en algunas versiones de Android tiene errores con SoftReferences: http://stackoverflow.com/questions/4014033 Hace que los cachés basados ​​en SoftReference sean prácticamente inútiles. – JBM

2

El problema es que SoftReferences son útiles para las asignaciones hechas en el espacio de montón de Java, pero las imágenes se asignan de forma nativa, por lo que este tipo de caché realmente no funcionará en Android.

+0

En realidad, almaceno imágenes en mi caché como matrices de bytes a medida que se reciben del servidor (la caché está en el nivel de conexión). Pero de todos modos, es una pista útil - ¡Gracias! – JBM

+0

@JBM si los almacena allí, realmente usa el doble de RAM que necesita, ya que los objetos de mapa de bits usan sus propios bytes. –

+0

Es un tema viejo, pero voy a responder de todos modos. En mi caso, solo se muestra un pequeño número de todas las imágenes obtenidas del servidor en un momento dado. Entonces no hay uso de doble RAM. De hecho, usamos caché de 2 niveles con el primer nivel en el disco y el segundo, más pequeño, en la memoria. Mi pregunta era sobre la optimización de la memoria. Veo mi culpa: debería haber hecho mi pregunta de una manera más abstracta; No debería haber dicho nada sobre servidores e imágenes porque esto pone a la gente pensando en una caja. – JBM

4

Si la memoria caché es usualmente tan pequeña como dices, puedes decidir una huella válida de tu aplicación y mantener tu propia memoria caché sin SoftReferences.

Por ejemplo, mediante un simple contador de bytes total: Simplemente agregue o mueva cualquier elemento utilizado al principio de una lista, agregue su tamaño al contador si es nuevo. Borre de la parte inferior si el total de bytes supera el límite de la regla del pulgar, disminuyendo así su contador. Tal vez la clase LinkedHashMap es útil para eso: Se puede usar como un caché como HashMap, pero también tiene un pedido como una lista.

1

no puede aumentar el tamaño de almacenamiento dinámico.

puede solicitar el uso de más mediante el uso de android: largeHeap = "verdadero" en el manifiesto, pero es posible que no obtenga más tamaño de almacenamiento dinámico de lo normal, ya que es solo una solicitud.

Además, puede utilizar la memoria nativa, por lo que realmente se saltea la limitación de tamaño de almacenamiento dinámico.

aquí están algunos de los puestos que he hecho al respecto:

y aquí es una biblioteca que he hecho por ella:

Cuestiones relacionadas