¿Cómo detecta mediante programación el tamaño de almacenamiento dinámico de la aplicación disponible para una aplicación de Android?
Escuché que hay una función que hace esto en versiones posteriores del SDK. En cualquier caso, estoy buscando una solución que funcione para 1.5 y más.
android
memory
heap
heap-memory
hpique
fuente
fuente
Respuestas:
Hay dos formas de pensar en su frase "tamaño de almacenamiento dinámico de aplicación disponible":
¿Cuánto montón puede usar mi aplicación antes de que se active un error grave? Y
¿Cuánto montón debería usar mi aplicación, dadas las limitaciones de la versión del sistema operativo Android y el hardware del dispositivo del usuario?
Hay un método diferente para determinar cada uno de los anteriores.
Para el artículo 1 anterior:
maxMemory()
que se puede invocar (por ejemplo, en el
onCreate()
método de su actividad principal ) de la siguiente manera:Este método le indica cuántos bytes totales de almacenamiento dinámico puede usar su aplicación .
Para el artículo 2 anterior:
getMemoryClass()
que se puede invocar de la siguiente manera:
Este método le indica aproximadamente cuántos megabytes de almacenamiento dinámico debe usar su aplicación si quiere respetar adecuadamente los límites del dispositivo actual y los derechos de otras aplicaciones para ejecutarse sin ser forzados repetidamente al ciclo
onStop()
/onResume()
ya que son groseramente se quedó sin memoria mientras su aplicación de elefante se bañaba en el jacuzzi de Android.Esta distinción no está claramente documentada, hasta donde yo sé, pero he probado esta hipótesis en cinco dispositivos Android diferentes (ver más abajo) y he confirmado para mi propia satisfacción que esta es una interpretación correcta.
Para una versión estándar de Android,
maxMemory()
generalmente devolverá aproximadamente la misma cantidad de megabytes que se indicangetMemoryClass()
(es decir, aproximadamente un millón de veces el último valor).La única situación (de la que tengo conocimiento) en la que los dos métodos pueden divergir es en un dispositivo rooteado que ejecuta una versión de Android como CyanogenMod, que permite al usuario seleccionar manualmente qué tan grande debe permitirse un tamaño de almacenamiento dinámico para cada aplicación. En CM, por ejemplo, esta opción aparece en "Configuración de CyanogenMod" / "Rendimiento" / "Tamaño de almacenamiento dinámico de VM".
NOTA: TENGA EN CUENTA QUE LA CONFIGURACIÓN DE ESTE VALOR MANUALMENTE PUEDE MENSAJAR SU SISTEMA, ESPECIALMENTE si selecciona un valor más pequeño de lo normal para su dispositivo.
Aquí están los resultados de mi prueba que muestran los valores devueltos por
maxMemory()
ygetMemoryClass()
para cuatro dispositivos diferentes que ejecutan CyanogenMod, utilizando dos valores de almacenamiento dinámico diferentes (configurados manualmente) para cada uno:Además de lo anterior, probé en una tableta Novo7 Paladin con Ice Cream Sandwich. Esta era esencialmente una versión estándar de ICS, excepto que he rooteado la tableta a través de un proceso simple que no reemplaza todo el sistema operativo, y en particular no proporciona una interfaz que permita que el tamaño del montón se ajuste manualmente.
Para ese dispositivo, aquí están los resultados:
También (por Kishore en un comentario a continuación):
Y (según el comentario de akauppi):
Por un comentario de cmcromance:
Y (según los comentarios del tencent):
Otros dispositivos
No he probado estos dos métodos con la opción de manifiesto especial android: largeHeap = "true" disponible desde Honeycomb, pero gracias a cmcromance y tencent tenemos algunos valores de muestra de largeHeap, como se informó anteriormente.
Mi expectativa (que parece estar respaldada por los números grandes de Heap anteriores) sería que esta opción tendría un efecto similar a la configuración manual del montón a través de un sistema operativo rooteado, es decir, aumentaría el valor de
maxMemory()
dejarlogetMemoryClass()
solo. Hay otro método, getLargeMemoryClass (), que indica la cantidad de memoria permitida para una aplicación que usa la configuración largeHeap. La documentación de getLargeMemoryClass () establece que "la mayoría de las aplicaciones no deberían necesitar esta cantidad de memoria y, en cambio, deberían permanecer con el límite getMemoryClass ()".Si lo he adivinado correctamente, usar esa opción tendría los mismos beneficios (y peligros) que usaría el espacio disponible por un usuario que ha aumentado el montón a través de un sistema operativo rooteado (es decir, si su aplicación usa la memoria adicional, probablemente no jugará tan bien con cualquier otra aplicación que el usuario esté ejecutando al mismo tiempo).
Tenga en cuenta que la clase de memoria aparentemente no necesita ser un múltiplo de 8 MB.
Podemos ver de lo anterior que el
getMemoryClass()
resultado no cambia para una configuración de dispositivo / SO dada, mientras que el valor maxMemory () cambia cuando el usuario configura el montón de manera diferente.Mi propia experiencia práctica es que en el G1 (que tiene una clase de memoria de 16), si selecciono manualmente 24 MB como tamaño de almacenamiento dinámico, puedo ejecutarlo sin errores incluso cuando mi uso de memoria puede aumentar a 20 MB (presumiblemente podría ir tan alto como 24 MB, aunque no he probado esto). Pero otras aplicaciones similares de gran tamaño pueden ser borradas de la memoria como resultado de la fragilidad de mi propia aplicación. Y, por el contrario, mi aplicación puede enjuagarse de la memoria si el usuario pone en primer plano estas otras aplicaciones de alto mantenimiento.
Por lo tanto, no puede superar la cantidad de memoria especificada por
maxMemory()
. Y, debe intentar mantenerse dentro de los límites especificados porgetMemoryClass()
. Una forma de hacerlo, si todo lo demás falla, podría ser limitar la funcionalidad de dichos dispositivos de manera que conserve la memoria.Finalmente, si planea superar el número de megabytes especificado
getMemoryClass()
, mi consejo sería trabajar mucho y duro para guardar y restaurar el estado de su aplicación, de modo que la experiencia del usuario sea prácticamente ininterrumpida si ocurre unonStop()
/onResume()
ciclo.En mi caso, por razones de rendimiento, estoy limitando mi aplicación a dispositivos que ejecutan 2.2 y superiores, y eso significa que casi todos los dispositivos que ejecutan mi aplicación tendrán una clase de memoria de 24 o superior. Por lo tanto, puedo diseñar para ocupar hasta 20 MB de almacenamiento dinámico y sentirme bastante seguro de que mi aplicación funcionará bien con las otras aplicaciones que el usuario puede estar ejecutando al mismo tiempo.
Pero siempre habrá algunos usuarios rooteados que hayan cargado una versión 2.2 o superior de Android en un dispositivo anterior (por ejemplo, un G1). Cuando encuentre una configuración de este tipo, idealmente, debería reducir el uso de su memoria, incluso si
maxMemory()
le dice que puede ir mucho más allá de los 16 MB quegetMemoryClass()
le indican que debe apuntar. Y si no se puede garantizar de manera fiable que su aplicación va a vivir dentro de ese presupuesto, entonces por lo menos asegurarse de queonStop()
/onResume()
funciona a la perfección.getMemoryClass()
, según lo indicado anteriormente por Diane Hackborn (hackbod), solo está disponible para volver al nivel 5 de API (Android 2.0), por lo que, como aconseja, puede asumir que el hardware físico de cualquier dispositivo que ejecute una versión anterior del sistema operativo está diseñado para soportar de manera óptima aplicaciones que ocupan un espacio dinámico de no más de 16 MB.Por el contrario,
maxMemory()
según la documentación, está disponible toda la parte trasera manera de nivel 1. APImaxMemory()
, en una versión pre-2.0, probablemente devolver un valor de 16 MB, pero yo hago ver que en mis (mucho más tarde) versiones de CyanogenMod del usuario puede seleccionar un valor de almacenamiento dinámico tan bajo como 12 MB, lo que presumiblemente daría como resultado un límite de almacenamiento dinámico más bajo, por lo que le sugiero que continúe probando elmaxMemory()
valor, incluso para versiones del sistema operativo anteriores a 2.0. Es posible que incluso deba negarse a ejecutar en el improbable caso de que este valor se establezca incluso por debajo de 16 MB, si necesita tener más de lo que semaxMemory()
indica.fuente
La API oficial es:
fuente
Debug.getNativeHeapSize()
hará el truco, debería pensar. Sin embargo, ha estado allí desde 1.0.La
Debug
clase tiene muchos métodos excelentes para rastrear asignaciones y otros problemas de rendimiento. Además, si necesita detectar una situación de poca memoria, consulteActivity.onLowMemory()
.fuente
Así es como lo haces:
Obtener el tamaño máximo de almacenamiento dinámico que la aplicación puede usar:
Obteniendo cuánto del montón utiliza actualmente su aplicación:
Obtener cuánto del montón puede usar ahora su aplicación (memoria disponible):
Y, para formatear bien cada uno de ellos, puede usar:
fuente
Esto devuelve el tamaño máximo de almacenamiento dinámico en bytes:
Estaba usando ActivityManager.getMemoryClass () pero en CyanogenMod 7 (no lo probé en otro lugar) devuelve un valor incorrecto si el usuario establece el tamaño del montón manualmente.
fuente
getMemoryClass
parece implicar que el número puede no ser el mismo que el tamaño de almacenamiento dinámico disponible para su vm, y dado que el documento paragetNativeHeapSize
es ... taciturno, realmente creo queRuntime.getRuntime().maxMemory()
es la mejor respuesta.Algunas operaciones son más rápidas que Java Heap Space Manager. Retrasar las operaciones por algún tiempo puede liberar espacio en la memoria. Puede usar este método para escapar del error de tamaño de almacenamiento dinámico:
fuente
AvailableMemoryPercentage
está de acuerdo con la fórmula: qué cantidad de memoria del dispositivo está actualmente libre.MIN_AVAILABLE_MEMORY_PERCENTAGE
es su parámetro personalizado, un umbral en el que comienza a esperar que el recolector de basura haga su trabajo.Asus Nexus 7 (2013) 32 Concierto: getMemoryClass () = 192 maxMemory () = 201326592
Cometí el error de crear un prototipo de mi juego en el Nexus 7, y luego descubrí que se quedó sin memoria casi de inmediato en la tableta genérica 4.04 de mi esposa (memoryclass 48, maxmemory 50331648)
Tendré que reestructurar mi proyecto para cargar menos recursos cuando determine que la clase de memoria es baja.
¿Hay alguna manera en Java para ver el tamaño actual del montón? (Puedo verlo claramente en logCat al depurar, pero me gustaría una forma de verlo en el código para adaptarlo, como si currentheap> (maxmemory / 2) descargue mapas de bits de alta calidad cargue baja calidad
fuente
¿Te refieres programáticamente, o solo mientras estás desarrollando y depurando? Si es lo último, puede ver esa información desde la perspectiva DDMS en Eclipse. Cuando su emulador (posiblemente incluso el teléfono físico que está enchufado) se esté ejecutando, enumerará los procesos activos en una ventana a la izquierda. Puede seleccionarlo y hay una opción para rastrear las asignaciones de almacenamiento dinámico.
fuente
el valor es b
el valor es MB
fuente
rt
? ¿Dónde se declara?