Este grupo especializado despúes de varios días de investigación y de recopilar de información, obtuvimos la solución, nuestro deseo es que todo este artículo sea de utilidad en tu trabajo.
Solución:
¿Cuál es la cantidad máxima de memoria (en megabytes / como porcentaje de la RAM total) que puede usar una aplicación de Android (que no es una aplicación del sistema)?
Eso varía según el dispositivo. getMemoryClass()
sobre ActivityManager
le dará el valor para el dispositivo en el que se está ejecutando su código.
¿Existen diferencias entre las versiones de Android?
Sí, en la medida en que los requisitos del sistema operativo han aumentado a lo largo de los años y los dispositivos deben adaptarse para que coincidan.
¿Existen diferencias con respecto al fabricante del dispositivo?
Sí, en la medida en que los fabricantes fabrican dispositivos y el tamaño varía según el dispositivo.
¿Qué “factores secundarios” se toman en consideración cuando se trata de determinar cuánta RAM puede usar una aplicación?
No tengo idea de lo que significa “factores secundarios”.
Los primeros dispositivos tenían un límite por aplicación de 16 MB; Los dispositivos posteriores aumentaron eso a 24 MB o 32 MB
Eso es correcto. La resolución de la pantalla es un factor determinante importante, ya que las resoluciones más grandes significan mapas de bits más grandes, por lo que las tabletas y los teléfonos de alta resolución tenderán a tener valores más altos todavía. Por ejemplo, verá dispositivos con 48 MB de montones, y no me sorprendería que hubiera valores superiores a ese.
¿Cómo es posible que las aplicaciones superen ese límite?
Supone que el autor de esa aplicación sabe lo que está haciendo. Teniendo en cuenta que el uso de la memoria de una aplicación es difícil de determinar para un ingeniero central de Android, no asumiría que la aplicación en cuestión necesariamente está proporcionando resultados particularmente precisos.
Dicho esto, el código nativo (NDK) no está sujeto al límite del montón. Y, desde Android 3.0, las aplicaciones pueden solicitar un “montón grande”, por lo general en el rango de cientos de MB, pero eso se considera una forma deficiente para la mayoría de las aplicaciones.
Además, noté que algunas aplicaciones mías fallan con una excepción OutOfMemoryException cuando se usan alrededor de 30-40 Megabytes.
Tenga en cuenta que el recolector de basura de Android no es un recolector de basura compactador. La excepción realmente debería ser CouldNotFindSufficientlyLargeBlockOfMemoryException
, pero probablemente se consideró demasiado prolijo. OutOfMemoryException
significa que tu no se pudo asignar el bloque solicitado, no es que hayas agotado tu montón por completo.
Es el final de 2018, así que las cosas han cambiado.
En primer lugar: ejecute su aplicación y abra la pestaña Android Profiler en Android Studio. Verás cuánta memoria consume, te sorprenderá pero puede destinar mucha RAM.
También aquí hay un gran artículo en documentos oficiales con instrucciones detalladas sobre cómo usar Memory Profiler que puede brindarle una visión en profundidad de la administración de su memoria.
Pero en la mayoría de los casos, su perfil de Android habitual será suficiente para usted.
Por lo general, una aplicación comienza con 50 Mb de asignación de RAM, pero salta instantáneamente hasta 90 Mb cuando comienza a cargar algunas fotos en la memoria. Cuando abre Actividad con un ViewPager con fotos precargadas (3,5 Mb cada una), puede obtener 190 Mb fácilmente en segundos.
Pero esto no significa que tenga problemas con la gestión de la memoria.
El mejor consejo que puedo darte es seguir las pautas y las mejores prácticas, usar las mejores bibliotecas para cargar imágenes (Glide, Picasso) y estarás bien.
Pero si necesita adaptar algo y realmente necesita saber cuánta memoria puede asignar manualmente, puede obtener la memoria libre total y calcular una parte predeterminada (en%) de ella. En mi caso, necesitaba almacenar en caché las fotos descifradas en la memoria para no tener que descifrarlas cada vez que el usuario se desliza por la lista.
Para este propósito, puede usar la clase LruCache lista para usar. Es una clase de caché que rastrea automáticamente la cantidad de memoria que asignan sus objetos (o el número de instancias) y elimina la más antigua para mantener la reciente según su historial de uso. Aquí hay un gran tutorial sobre cómo usarlo.
En mi caso, creé 2 instancias de cachés: para pulgares y archivos adjuntos. Los hizo static con acceso singleton para que estén disponibles globalmente en toda la aplicación.
clase de caché:
public class BitmapLruCache extends LruCache
private static final float CACHE_PART_FOR_THUMBS_PRC = 0.01f; // 1% (Nexus 5X - 5Mb)
private static final float CACHE_PART_FOR_ATTACHMENTS_PRC = 0.03f;// 3% (Nexus 5X - 16Mb)
private static BitmapLruCache thumbCacheInstance;
private static BitmapLruCache attachmentCacheInstance;
public static synchronized BitmapLruCache getDecryptedThumbCacheInstance()
if (thumbCacheInstance == null)
int cacheSize = getCacheSize(CACHE_PART_FOR_THUMBS_PRC);
//L.log("creating BitmapLruCache for Thumb with size: " + cacheSize + " bytes");
thumbCacheInstance = new BitmapLruCache(cacheSize);
return thumbCacheInstance;
else
return thumbCacheInstance;
public static synchronized BitmapLruCache getDecryptedAttachmentCacheInstance()
if (attachmentCacheInstance == null)
int cacheSize = getCacheSize(CACHE_PART_FOR_ATTACHMENTS_PRC);
// L.log("creating BitmapLruCache for Attachment with size: " + cacheSize + " bytes");
attachmentCacheInstance = new BitmapLruCache(cacheSize);
return attachmentCacheInstance;
else
return attachmentCacheInstance;
private BitmapLruCache(int maxSize)
super(maxSize);
public void addBitmap(Uri uri, byte[] bitmapBytes)
if (get(uri) == null && bitmapBytes != null)
put(uri, bitmapBytes);
public byte[] getBitmap(Uri uri)
return get(uri);
@Override
protected int sizeOf(Uri uri, byte[] bitmapBytes)
// The cache size will be measured in bytes rather than number of items.
return bitmapBytes.length;
Así es como calculo la RAM libre disponible y cuánto puedo aprovechar:
private static int getCacheSize(float partOfTotalFreeMemoryToUseAsCache)
final long maxMemory = Runtime.getRuntime().maxMemory();
//Use ... of available memory for List Notes thumb cache
return (int) (maxMemory * partOfTotalFreeMemoryToUseAsCache);
Y así es como lo uso en Adapters para obtener una imagen en caché:
byte[] decryptedThumbnail = BitmapLruCache.getDecryptedThumbCacheInstance().getBitmap(thumbUri);
y cómo lo configuro en el caché en el hilo de fondo (AsyncTask regular):
BitmapLruCache.getDecryptedThumbCacheInstance().addBitmap(thumbUri, thumbBytes);
Mi aplicación apunta a API 19+, por lo que los dispositivos no son viejos y estas porciones de RAM disponible son lo suficientemente buenas para el caché en mi caso (1% y 3%).
Hecho de la diversión: Android no tiene API ni otros trucos para obtener la cantidad de memoria asignada a su aplicación, se calcula sobre la marcha en función de varios factores.
PD Estoy usando un static class para almacenar un caché, pero de acuerdo con las últimas pautas de Android, se recomienda usar el componente de arquitectura ViewModel para ese propósito.
Los límites de memoria por aplicación están aquí según el tamaño de la pantalla y la versión de Android: https://drive.google.com/file/d/0B7Vx1OvzrLa3Y0R0X1BZbUpicGc/view?usp=sharing
Fuente: Descargas de compatibilidad con Android http://source.android.com/compatibility/downloads.html; Documento de definición de compatibilidad (CDD), sección Compatibilidad de máquina virtual o Compatibilidad en tiempo de ejecución
Puedes sustentar nuestra ocupación poniendo un comentario o dejando una puntuación te lo agradecemos.