android - vib - Cómo manejar OutOfMemoryError
vsphere web client 6.5 download (7)
En mi aplicación tengo fotos, videos, etc. En el caso de las imágenes, he realizado el escalado, pero a veces me sale un OutOfMemoryError
. ¿Cómo puedo manejar el error de manera eficiente?
Comencé a probar esta rutina que carga un jpeg en un ImageView y comprueba si hay memoria insuficiente y vuelve a escalar hasta que se ajusta.
static public boolean tryJpegRead(ImageView imageView, File fn){
if (!fn.exists()){
Log.d("ANDRO_ASYNC",String.format("missing file %s",fn.getAbsolutePath()));
return false;
}
BitmapFactory.Options o = new BitmapFactory.Options();
for (int i = 1; i<10; i++){
o.inSampleSize = i;
o.inJustDecodeBounds = true;
BitmapFactory.decodeFile(fn.getAbsolutePath(), o);
int h = o.outHeight;
int w = o.outWidth;
Log.d("ANDRO_ASYNC",String.format("going in h=%d w=%d resample = %d",h,w,o.inSampleSize));
o.inJustDecodeBounds = false;
try{
imageView.setImageBitmap(
Bitmap.createScaledBitmap(
BitmapFactory.decodeFile(fn.getAbsolutePath(), o),
w,
h,
true));
return true; // only happens when there is no error
}catch(OutOfMemoryError E){
Log.d("ANDRO_ASYNC",String.format("catch Out Of Memory error"));
// E.printStackTrace();
System.gc();
}
}
return false;
}
Cuando se trata de errores de OutOfMemory relacionados con la manipulación de mapas de bits, verificar el tamaño del mapa de bits descodificado es la mejor opción, y hasta donde conozco solo. El código sigue:
public static BitmapFactory.Options getBitmapOptionsWithoutDecoding(String url){
BitmapFactory.Options opts = new BitmapFactory.Options();
opts.inJustDecodeBounds = true;
BitmapFactory.decodeFile(url, opts);
return opts;
}
public static int getBitmapSizeWithoutDecoding(String url){
BitmapFactory.Options opts = getBitmapOptionsWithoutDecoding(url);
return opts.outHeight*opts.outWidth*32/(1024*1024*8);
}
//ref:http://.com/questions/6073744/android-how-to-check-how-much-memory-is-remaining
public static double availableMemoryMB(){
double max = Runtime.getRuntime().maxMemory()/1024;
Debug.MemoryInfo memoryInfo = new Debug.MemoryInfo();
Debug.getMemoryInfo(memoryInfo);
return (max - memoryInfo.getTotalPss())/1024;
}
public static final long SAFETY_MEMORY_BUFFER = 10;//MB
public static boolean canBitmapFitInMemory(String path){
long size = getBitmapSizeWithoutDecoding(path);
Log.d(TAG, "image MB:"+size);
return size <= availableMemoryMB() - SAFETY_MEMORY_BUFFER;
}
ref: http://developer.android.com/training/displaying-bitmaps/load-bitmap.html
En caso de que tengas imágenes grandes como fondos o similares, una forma fácil de evitar el agotamiento de la memoria es mover las imágenes de drawable-xhdpi a drawable-nodpi, pero ten cuidado, esto cargará el mapa de bits sin ninguna modificación. La buena forma de utilizar BitmapFactory.options
ajusta a su necesidad.
Hay un método en la actividad que se llama cuando el dispositivo tiene poca memoria, pero solo se puede usar para activar la limpieza de los archivos de caché. Esto no significa que su proceso de solicitud esté saliendo de la memoria.
También puede agregar un bloque try catch para capturar Error o OutOfMemoryError, pero esto sería demasiado tarde.
El manejo de grandes cantidades de mapas de bits o mapas de bits grandes es realmente difícil en las aplicaciones de Android. Encontrarás algunos consejos sobre este tema en este artículo de Romain Guy.
También puede encargarse de cargar mapas de bits directamente a la resolución que necesita especificando un tamaño de muestra en las BitmapFactory.options Que proporciona a los métodos BitmapFactory.decode * ().
OutOfMemory no puede ser manejado. ¿Qué piensas?
La memoria del dispositivo está llena, obtuviste la excepción y luego mágicamente haces algo que elimina la excepción y ahora tienes más recursos. Eso es imposible, ya sabes.
OutOfMemory debe evitarse, no manejarse después de que ocurra.
Verifique que el tamaño de la imagen sea más pequeño que la memoria disponible antes de intentar cargarla. Por lo tanto, la forma más eficiente de manejar OutOfMemoryException es crear una arquitectura de su aplicación de tal manera que nunca intente cargar gran cantidad de datos en la memoria para evitar la excepción.
Use android: allowBackup = "true", android: hardwareAccelerated = "false" y android: largeHeap = "true" para resolver esto
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher"
android:hardwareAccelerated="false"
android:largeHeap="true"
android:theme="@style/AppTheme">