2012-01-26 14 views
5

CONFIGURACIÓN:Memoria y Actividades :: OutOfMemory

tengo esta aplicación que cuenta con 4 actividades en una trayectoria lineal, la navegación muy simple: A -> B -> C -> D

Todos las actividades comparten la misma imagen de fondo y todas tienen un par de botones regulares, una vista de texto o un texto de edición. Todos los cuales están definidos en vistas separadas de archivos xml.

El fondo es un gradiente y es algo pesado. Alrededor de 3 megas como un mapa de bits sin comprimir.

La aplicación no hace nada, sin embargo, la única lógica en ella, es para el inicio de las actividades y el cierre de los clics en el botón

He intentado utilizar MAT para encontrar una pérdida de memoria, pero no pude encontrar nada. El mayor tamaño retenido en mi aplicación es 656 (¿ko?) El tamaño total retenido para la aplicación es 1520 (¿ko?) Y no puedo encontrar ningún objeto que se haya duplicado. que por cierto se contradice por completo dumpsys que muestra 27300 (? Ko) asignados

PROBLEMAS:

  1. Cuando navegue hacia arriba, veo un aumento del uso de memoria equivalente al tamaño del fondo.
  2. Cuando navego hacia ABAJO, cerrando las actividades con el botón Atrás o un comando de finalización, el uso de memoria de la aplicación no disminuye.
  3. Si voy de A a D, vuelvo a B y giro la pantalla, la fuerza de la aplicación se cierra con una Excepción de OutOfMemory.

PREGUNTAS:

Actualización: supongo que la verdadera pregunta es ¿por qué tengo una enorme pérdida de memoria (5 megas a la vez) con un tamaño aplicación 27megs en tiempo de congelación y no puedo verlo en el MAT?

  1. ¿Por qué Android descomprimiría varias veces el mismo fondo, una vez por actividad? Parece ineficiente.
  2. ¿Es posible solucionar este problema usando temas o veré la misma rareza de "asignar 1 fondo por actividad"?
  3. ¿Por qué las actividades no se recuperan cuando se cierran?
  4. ¿Por qué MAT y dumpsys presentan números diferentes?

CLAVES

exactamente al mismo tiempo que tengo: dumpsys meminfo:

Applications Memory Usage (kB): 
Uptime: 74006853 Realtime: 110962243 

** MEMINFO in pid 22683 [com.kayenko.sosadresse] ** 
        native dalvik other total 
      size: 20820  5767  N/A 26587 
     allocated: 18751  2901  N/A 21652 
      free:  312  2866  N/A  3178 
      (Pss):  1357  201 16782 18340 
    (shared dirty):  2264  1804  5456  9524 
    (priv dirty):  1280  116 16032 17428 

Objects 
      Views:  0  ViewRoots:  0 
    AppContexts:  0  Activities:  0 
      Assets:  2 AssetManagers:  2 
    Local Binders:  18 Proxy Binders:  16 
Death Recipients:  1 
OpenSSL Sockets:  0 

SQL 
       heap:  0   MEMORY_USED:  0 
PAGECACHE_OVERFLOW:  0   MALLOC_SIZE:  0 

Y este árbol dominador:

MAT Dominator tree

Thansk a cualquier persona con una pista sobre lo que soy Supongo que debes buscar.

Respuesta

7

La memoria es un tema muy complicado en Android.

Cada aplicación obtiene un límite de memoria de montón dependiendo del dispositivo. Esta memoria del montón es la memoria dalvik más la memoria nativa, y puede verla como la columna total en los resultados dumpsys meminfo. La memoria dalvik trata con todo, excepto con los bitmaps, que están asignados en la memoria nativa (esto es cierto para las versiones de Android anteriores a Honeycomb).

Dicho esto solo puedo contestar a algunas de sus preguntas:

  1. Por lo que yo sé, Android siempre asignará memoria de mapas de bits, incluso si son de la misma. Por lo tanto, en su caso, cada actividad asigna memoria para su fondo.

  2. No sé si es mejor trabajar con temas, tendrás que intentarlo.

  3. Por un lado, las actividades no se recuperan cuando el dispositivo tiene suficiente memoria para ocuparse de la siguiente actividad. Cada actividad se lleva a una pila desde donde se recupera cuando presionas el botón Atrás. En caso de que Android necesite más memoria, elimina una actividad de la pila desasignando su memoria (volviendo a la pregunta número uno, quizás esta es la razón por la cual no se comparte la memoria). Por otro lado, puede configurar las actividades launchMode para cambiar este comportamiento (eche un vistazo a here).

  4. Creo que MAT no muestra datos de la memoria nativa. Use la columna nativa de dumpsys meminfo para ver cuánta memoria asignada tiene para Bitmaps.

He tenido problemas para manejar los problemas de OutOfMemory. Ahora tengo una idea mucho más clara de cómo funciona y puedo trabajar con archivos de gran tamaño sin quedarse sin memoria. Yo recomendaría estos dos recursos que me ayudaron mucho:

Buena suerte!

+0

Gracias Xavi, esto fue muy informativo. Ya había visto los enlaces que me diste pero desafortunadamente no hubo nada. No sabía sobre el modo de lanzamiento y debo admitir que no entendí nada de lo que se supone que debe hacer. Supongo que tendré que probarlo porque la documentación está "ausente" como de costumbre. :) – Yahel

+1

Sin embargo, marcaré su respuesta como la respuesta porque realmente me dio 3 respuestas de 4: D – Yahel

0

Necesita reciclar explícitamente el mapa de bits utilizado como fondo al destruir su actividad. Código será la siguiente:

@Override 
protected void onDestroy() { 
    Drawable drawable = getView().getBackground(); 
    if (drawable instanceof BitmapDrawable) { 
     ((BitmapDrawable)drawable).getBitmap().recycle(); 
    } 
    drawable.setCallback(null); 
    getView().setBackgroundDrawable(null); 
    super.onDestroy(); 
} 

Tal vez necesita liberar recursos de forma recursiva para las vistas anidadas, pero depende de la estructura de su diseño. Este es el caso general

+0

Gracias por la entrada, lamentablemente no sirvió de nada. Ninguno de mis widgets tiene bitmapdrawables de acuerdo con su código y también probé el código de esta página: http://www.alonsoruibal.com/bitmap-size-exceeds-vm-budget/ y luego una combinación de los dos para ser tan lo más agresivo posible pero fue en vano. – Yahel

+0

No estoy de acuerdo. Dalvik reciclará bitmaps automáticamente una vez que ya no haya más referencias al mismo. No es necesario hacerlo a mano, existe el método recycle() para que pueda apurar este proceso y reclamar la memoria con anticipación. –

4

Así que después de horas de investigación y la ayuda de Xavi aquí están los resultados:

P. ¿Por qué Android descomprimir varias veces el mismo fondo, una vez por la actividad? Parece ineficiente.

A. Aunque parece lógico tener algún tipo de forma de pedir que un mapa de bits se comparta entre actividades ya que estamos en dispositivos móviles con poca memoria, esto no parece existir en Android. Cada vez que se usa un mapa de bits en diferentes actividades, no se descomprime en la memoria nativa.

P. ¿Es posible superar este problema usando temas o veré la misma rareza de "asignar un mapa de bits por actividad"?

Después de la experimentación, la memoria consumida utilizando temas no difiere en absoluto de la cantidad de memoria utilizada al establecer explícitamente el mapa de bits en el xml de los diseños. Esto es extraño para mí, ya que el estilo se trata de agrupar atributos en un mismo lugar.

P. ¿Por qué las actividades no se recuperan cuando se cierran?

A. Bueno, no estoy seguro, pero lo que encontré es que esto me dio OOM errores casi solo cuando se depura. Al iniciar la aplicación desde el dispositivo, casi nunca sucedió. ¿Un error en el proceso de depuración? Pruébalo antes de perder 5 horas probando un trillón.

P. ¿Por qué MAT y dumpsys presentan números diferentes?

A. La respuesta de Xavi es correcta, dumpsys meminfo muestra toda la memoria asignada (nativa + dalvik) mientras que MAT muestra solo la de Dalvik. Dado que los píxeles de mapas de bits están asignados en la memoria nativa, MAT no lo verá. Esto solo es cierto antes de Android 3.0, donde cambiaron el esquema de asignación e hicieron que los datos de píxel del mapa de bits encajaran en Dalvik.

P. ¿Cómo he podido solucionar mi problema

A. En primer lugar esto no podría haber sido un problema cuando no depuración. En segundo lugar, para estar en el lado seguro Substituí el gradiente png con una forma con un gradiente radial y utilizamos el

getWindow().setFormat(PixelFormat.RGBA_8888); 
getWindow().addFlags(WindowManager.LayoutParams.FLAG_DITHER); 

en el OnCreate de mis actividades para tratar de evitar las bandas. Todavía tendré bandas en algunos dispositivos, pero prefiero tener bandas que en los FC

Cuestiones relacionadas