Si tu aplicación es lenta en algunos dispositivos o las funciones de ejecución instantánea de Android Studio dejan de funcionar aleatoriamente, entonces podrías estar experimentando fugas de memoria.
¿Cuándo se produce una fuga de memoria?
Una de las grandes cosas de Java es el recolector de basura (GC). Un recolector de basura se ejecuta periódicamente para comprobar los objetos que no están en uso y los elimina. Una fuga de memoria ocurrirá cuando hay objetos que no están en uso por la aplicación pero el recolector de basura no puede reconocerlos. Por lo tanto, permanecerán en la memoria sin usar, reduciendo la cantidad de memoria disponible para la aplicación, lo que provoca resultados inesperados.
¿Cómo detectar las fugas de memoria?
Hay varias maneras de hacerlo. Vamos a cubrir algunas de ellas en este artículo.
Pero primero, vamos a escribir algo de código que podría producir una fuga de memoria. Crearemos una app con dos actividades. La actividad A tendrá un botón que abre la actividad B. Junto a esto, también crearemos una clase singleton que contenga una referencia estática de un Contexto.
clase Manager {
private static Manager ourInstance;
private Context context;
static Manager getInstance(Context context) {
if (ourInstance == null) {
ourInstance = new Manager(context);
}
return ourInstance;
}
private Manager(Context context) {
this.context = context;
}
}
Vamos a llamar a este singleton desde la Actividad A
Manager.getInstance(this);
Detección de fugas de memoria usando los monitores de Android Studio
Android Studio proporciona herramientas muy útiles para perfilar el rendimiento de tu aplicación, y una de ellas es el Memory Monitor. Podemos utilizar el Memory Monitor para detectar fugas de memoria mediante los siguientes pasos:
1. Ejecuta tu app en tu dispositivo móvil o en un emulador.
2. Abre Android Monitor (Pulsa Cmd + 6 en Mac o Alt + 6 en Windows). En la parte superior de Memory Monitor, haz clic en Start Allocation Tracking.
3. Utiliza la app alrededor de la parte que sospechas que puede estar experimentando una fuga de memoria. En nuestro ejemplo, iremos a otra actividad.
4. Haga clic en Iniciar GC para forzar al recolector de basura a empezar a recoger los objetos que no están actualmente en uso y eliminarlos. Deberías ver que el gráfico de memoria disminuye un poco.
5. Haz clic en Dump Java Heap para que Android Studio genere un archivo .hprof que contenga una instantánea del heap. La forma más fácil de comprobar una fuga de memoria es utilizando Analyzer Tasks
6. Abre la pestaña Analyzer Tasks y luego haz clic en Run en la parte superior de esta pestaña. Deberías ver las actividades filtradas en la pestaña de Resultados de Análisis debajo de la pestaña de Tareas del Analizador.
Detectar fugas de memoria usando Leak Canary
Leak Canary es una librería hecha por Square y es una forma muy rápida de detectar fugas de memoria. Leak Canary te permite detectar fugas de memoria en ejecuciones más largas porque no necesitas conectar tu dispositivo al Android Studio y monitorizar tu aplicación durante un largo periodo de tiempo. Leak Canary le enviará notificaciones cada vez que haya una fuga de memoria.
La integración de Leak Canary es realmente fácil. Todo lo que necesitas hacer es añadir lo siguiente a tu archivo build.gradle a nivel de aplicación:
dependencias {
debugCompile ‘com.squareup.leakcanary:leakcanary-android:1.5.1’
releaseCompile ‘com.squareup.leakcanary:leakcanary-android-no-op:1.5.1’
testCompile ‘com.squareup.leakcanary:leakcanary-android-no-op:1.5.1’
}
Entonces añade el siguiente código a tu clase Application:
@Override public void onCreate() {
super.onCreate();
if (LeakCanary.isInAnalyzerProcess(this)) {
// Este proceso está dedicado a LeakCanary para el análisis del heap.
// No debes init tu app en este proceso.
return;
}
LeakCanary.install(this);
// Código normal de init de la app…
}
Y ya está, puedes empezar.
Detectar posibles fugas con Infer
Infer es una herramienta de análisis estático hecha por Facebook que te ayuda a encontrar posibles excepciones de puntero nulo y fugas de recursos, así como alcance de anotaciones, guardias de bloqueo perdidas y condiciones de carrera de concurrencia. Es una buena herramienta para añadir a su CI para superar todos los posibles errores. También es de código abierto, por lo que el desarrollo de la herramienta sigue evolucionando. Puedes encontrar más información sobre Infer en su documentación de inicio rápido.