telefono - Fugas de memoria en la aplicación de Android
porque mi celular dice memoria llena si no tengo nada (1)
Estoy experimentando algunas pérdidas de memoria en mi aplicación. La primera vez que sospeché que había una pérdida de memoria fue cuando hice una prueba de estrés de mi aplicación presionando un botón para comenzar una nueva Activity
. Después de usar DDMS
y descargar un .hprof file
, este archivo lo abrí con Eclipse Memory Analyzer
Obtuve tres posibles Fugas de memoria, que se muestran en un gráfico circular:
Y una descripción de las fugas de memoria:
Sospechoso 1
122 instancias de "android.widget.LinearLayout", cargadas por "" ocupan 29 585 384 (38,74%) bytes.
Las instancias más grandes:
•android.widget.LinearLayout @ 0x4258c008 - 2 268 848 (2,97%) bytes.
•android.widget.LinearLayout @ 0x425c8688 - 2 268 848 (2,97%) bytes.
•android.widget.LinearLayout @ 0x425e3988 - 2 268 848 (2,97%) bytes.
•android.widget.LinearLayout @ 0x4296e198 - 2 268 848 (2,97%) bytes.
•android.widget.LinearLayout @ 0x429d3aa8 - 2 268 848 (2,97%) bytes.
•android.widget.LinearLayout @ 0x42a10c78 - 2 268 848 (2,97%) bytes.
•android.widget.LinearLayout @ 0x448a1f10 - 2 268 848 (2,97%) bytes.
•android.widget.LinearLayout @ 0x44a65d58 - 2 268 848 (2,97%) bytes.
•android.widget.LinearLayout @ 0x42a14098 - 2 268 824 (2,97%) bytes.
•android.widget.LinearLayout @ 0x4258bd30 - 999 528 (1,31%) bytes.
•android.widget.LinearLayout @ 0x425c83b0 - 999 528 (1,31%) bytes.
•android.widget.LinearLayout @ 0x425ddff8 - 999 528 (1,31%) bytes.
•android.widget.LinearLayout @ 0x4296df80 - 999 528 (1,31%) bytes.
•android.widget.LinearLayout @ 0x42a109a0 - 999 528 (1,31%) bytes.
•android.widget.LinearLayout @ 0x42a13dc0 - 999 528 (1,31%) bytes.
•android.widget.LinearLayout @ 0x448a1c38 - 999 528 (1,31%) bytes.
•android.widget.LinearLayout @ 0x448cc338 - 999 528 (1,31%) bytes.
•android.widget.LinearLayout @ 0x44a65a80 - 999 528 (1,31%) bytes.
Sospechoso 2
15 instancias de "android.widget.FrameLayout", cargadas por "" ocupan 29 405 016 (38,51%) bytes.
Las instancias más grandes:
•android.widget.FrameLayout @ 0x4245b490 - 3 266 728 (4,28%) bytes.
•android.widget.FrameLayout @ 0x4247a330 - 3 266 728 (4,28%) bytes.
•android.widget.FrameLayout @ 0x425aa1d8 - 3 266 728 (4,28%) bytes.
•android.widget.FrameLayout @ 0x425df8b0 - 3 266 728 (4,28%) bytes.
•android.widget.FrameLayout @ 0x425efe68 - 3 266 728 (4,28%) bytes.
•android.widget.FrameLayout @ 0x42627590 - 3 266 728 (4,28%) bytes.
•android.widget.FrameLayout @ 0x42987a70 - 3 266 728 (4,28%) bytes.
•android.widget.FrameLayout @ 0x4299df20 - 3 266 728 (4,28%) bytes.
•android.widget.FrameLayout @ 0x448b6f28 - 3 266 728 (4,28%) bytes.
Sospechoso 3
2 682 instances of "java.lang.Class", loaded by "<system class loader>" occupy 8 662 744 (11,34%) bytes.
Biggest instances:
•class android.content.res.Resources @ 0x41a4f708 - 7 485 176 (9,80%) bytes.
Mi primer pensamiento fue buscar en el archivo R.java
, porque podía ver algunas referencias hexadecimales a la posible pérdida de memoria. Intenté buscar la cadena hexadecimal de Eclipse Memory Analyzer, pero no pude encontrar las direcciones en el archivo R.java
.
Luego miré en el Árbol Dominador, y este es el resultado:
Esta es solo la primera entrada en la lista, pero esta es la más grande.
Con esta información, ¿alguien puede darme una pista sobre cómo puedo rastrear la pérdida de memoria? Agregar un comentario si necesito agregar información adicional a esta publicación.
Gracias por adelantado.
EDITAR
El problema puede estar en mi clase Base. Todas las actividades heredan de esta clase. Este trabajo de clases es configurar un SlidingMenu, en la esquina superior izquierda. Este es el código para esta clase:
public class Base extends Activity implements OnSlideMenuItemClickListener {
public SlideMenu slidemenu;
ImageButton b;
Time t;
BluetoothCommunicator btCom;
BroadcastReceiver btBroadCaster;
MonitorBluetoothState bluetoothState;
public void setTab(int id) {
setContentView(id);
overridePendingTransition(R.anim.activityfade, R.anim.activityfadeout);
slidemenu = (SlideMenu) findViewById(R.id.slideMenu);
slidemenu.init(this, R.menu.slide, this, 450);
slidemenu.setHeaderImage(getResources().getDrawable(R.drawable.ic_launcher));
b = (ImageButton) findViewById(R.id.BtnSlide);
b.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
slidemenu.show();
}
});
b.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
b.setImageResource(R.drawable.lincolor);
break;
case MotionEvent.ACTION_UP:
b.setImageResource(R.drawable.lin);
break;
}
return false;
}
});
}
@Override
public void onSlideMenuItemClick(int itemId) {
Class<?> cls = null;
switch(itemId) {
case R.id.item_one:
cls = Home.class;
break;
case R.id.item_two:
cls = History.class;
break;
case R.id.item_three:
cls = ClearHistoryDialog.class;
break;
case R.id.item_four:
cls = SendLogDialog.class;
break;
case R.id.item_five:
cls = PasswordDialog.class;
break;
case R.id.item_six:
cls = About.class;
break;
}
Intent intent = new Intent(this, cls);
startActivity(intent);
}
}
En mis otras actividades, este método setTab se llamará así:
public class Main extends Base {
public void onCreate(Bundle b) {
super.onCreate(b);
super.setTab(R.layout.Home);
}
}
Donde el diseño de casa es así:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/parent"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#e4e8ed"
android:gravity="top" >
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/first"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="0px" >
<include
android:id="@+id/tabBar"
layout="@layout/tab" />
<com.workspace.tobias
android:id="@+id/slideMenu"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<Button
android:id="@+id/nist"
android:layout_width="match_parent"
android:layout_height="67dp"
android:layout_gravity="center_horizontal"
android:layout_marginBottom="3dp"
android:layout_marginLeft="3dp"
android:layout_marginRight="3dp"
android:layout_marginTop="3dp"
android:background="@drawable/ready"
android:textColor="#FFFFFF" />
<ListView
android:id="@+id/lastCases"
android:layout_width="fill_parent"
android:layout_height="fill_parent" />
</LinearLayout>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/loading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_marginTop="300dp"
android:orientation="horizontal" >
<ProgressBar
android:id="@+id/progress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminate="true" />
<TextView
android:id="@+id/loadingCases"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:text="@string/Loading"
android:textColor="#707070"
android:textSize="18dp"
android:layout_marginLeft="10dp" />
</LinearLayout>
</RelativeLayout>
¿Utiliza variables estáticas para almacenar grandes recursos en caché?
Si es así, entonces es un error común en las aplicaciones de Android usar el contexto de actividad para cargar tales recursos. Esto lleva a sostener las actividades y todos sus recursos, aunque ya no sean necesarios.
Para corregir este contexto de aplicación de uso para cargar tales recursos!
Puede consultar esta publicación del blog de desarrolladores de Android para obtener más detalles.