recoleccion programacion memoria liberar leaks basura avoid android memory-leaks

android - memoria - recoleccion de basura en programacion



¿Qué herramientas y métodos de Android funcionan mejor para encontrar fugas de memoria/recursos? (7)

Buenas conversaciones de Google I / O (2011) sobre Administración de memoria en Android, así como detalles sobre herramientas + técnicas para el perfil de memoria:
http://www.youtube.com/watch?v=_CruQY55HOk

Tengo una aplicación para Android desarrollada, y estoy en el punto de desarrollo de una aplicación de teléfono donde todo parece funcionar bien y quieres declarar la victoria y el envío, pero sabes que solo tiene que haber algunas fugas de memoria y recursos. ahí; y solo hay 16mb de Heap en Android y es aparentemente sorprendentemente fácil de filtrar en una aplicación de Android.

He estado buscando y hasta ahora solo he podido encontrar información sobre ''hprof'' y ''traceview'' y ninguno recibe muchas críticas favorables.

¿Qué herramientas o métodos has encontrado o desarrollado y que te interesan compartir en un proyecto de sistema operativo?


Bueno, esas son las herramientas que se conectan con los formatos únicos que usa Android. Creo que con lo que puede estar insatisfecho es con el marco subyacente del código de prueba en uso.

¿Has probado simulando áreas de código de prueba con el Android Mock Framework?


La respuesta de @ hp.android funciona bien si solo está trabajando con fondos de mapa de bits pero, en mi caso, tenía un BaseAdapter proporcionaba un conjunto de ImageView para un GridView . unbindDrawables() método unbindDrawables() como se aconseja para que la condición sea:

if (view instanceof ViewGroup && !(view instanceof AdapterView)) { ... }

pero el problema es que el método recursivo nunca procesa los elementos AdapterView de AdapterView . Para abordar esto, hice lo siguiente:

if (view instanceof ViewGroup) { ViewGroup viewGroup = (ViewGroup) view; for (int i = 0; i < viewGroup.getChildCount(); i++) unbindDrawables(viewGroup.getChildAt(i)); if (!(view instanceof AdapterView)) viewGroup.removeAllViews(); }

para que los hijos de AdapterView todavía se procesen, el método simplemente no intenta eliminar todos los elementos AdapterView (que no es compatible).

Sin embargo, esto no soluciona el problema ya que ImageView s administra un mapa de bits que no es su fondo. Por lo tanto, agregué lo siguiente. No es ideal, pero funciona:

if (view instanceof ImageView) { ImageView imageView = (ImageView) view; imageView.setImageBitmap(null); }

En general, el método unbindDrawables() es:

private void unbindDrawables(View view) { if (view.getBackground() != null) view.getBackground().setCallback(null); if (view instanceof ImageView) { ImageView imageView = (ImageView) view; imageView.setImageBitmap(null); } else if (view instanceof ViewGroup) { ViewGroup viewGroup = (ViewGroup) view; for (int i = 0; i < viewGroup.getChildCount(); i++) unbindDrawables(viewGroup.getChildAt(i)); if (!(view instanceof AdapterView)) viewGroup.removeAllViews(); } }

Espero que haya un enfoque más basado en principios para liberar tales recursos.



Sobre todo para los viajeros de Google del futuro:

Lamentablemente, la mayoría de las herramientas de Java no son adecuadas para esta tarea, ya que solo analizan JVM-Heap. Cada aplicación de Android también tiene un montón nativo, que también tiene que caber dentro del límite de ~ 16 MB. Por lo general, se usa para datos de mapa de bits. Por lo tanto, puede ejecutar con bastante facilidad los errores de falta de memoria incluso si su JVM-Heap se está enfriando alrededor de 3 MB, si usa muchos elementos extraíbles.


Uno de los errores más comunes que encontré al desarrollar aplicaciones de Android es el error "java.lang.OutOfMemoryError: Tamaño de mapa de bits supera el presupuesto de VM". Encontré este error frecuentemente en actividades que usan muchos mapas de bits después de cambiar de orientación: la actividad se destruye, se crea nuevamente y los diseños se "inflan" desde el XML consumiendo la memoria VM disponible para bitmaps.

Los mapas de bits en el diseño de actividad anterior no son desasignados correctamente por el recolector de basura porque han cruzado referencias a su actividad. Después de muchos experimentos, encontré una solución bastante buena para este problema.

Primero, configure el atributo "id" en la vista principal de su diseño XML:

<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:id="@+id/RootView" > ...

Luego, en el método onDestroy () de tu Actividad, llama al método unbindDrawables () pasando una referencia a la Vista padre y luego haz un System.gc ()

@Override protected void onDestroy() { super.onDestroy(); unbindDrawables(findViewById(R.id.RootView)); System.gc(); } private void unbindDrawables(View view) { if (view.getBackground() != null) { view.getBackground().setCallback(null); } if (view instanceof ViewGroup) { for (int i = 0; i < ((ViewGroup) view).getChildCount(); i++) { unbindDrawables(((ViewGroup) view).getChildAt(i)); } ((ViewGroup) view).removeAllViews(); } }

Este método unbindDrawables () explora el árbol de vista recursivamente y:

  1. Elimina las devoluciones de llamada en todos los diseños arrastrables
  2. Elimina niños en cada grupo de vista