Detectando OutOfMemoryError en la decodificación Bitmap
¿Es una buena práctica capturar OutOfMemoryError incluso si ha intentado alguna manera de reducir el uso de memoria? ¿O deberíamos simplemente no capturar la excepción? ¿Cuál es la mejor práctica?
try { BitmapFactory.Options options = new BitmapFactory.Options(); options.inSampleSize = 4; bitmap = BitmapFactory.decodeFile(file, options); } catch (OutOfMemoryError e) { e.printStackTrace(); }
Gracias
- Android tratando de redondear las esquinas de mapa de bits
- Diff b / w bitmap.recycle () y bitmap = nulo
- Cómo establecer el tamaño del mapa de bits en ZXing?
- Dibujar círculo en mapa de bits
- Android - Definir el fondo de la aplicación
- Manejo de mapas de bits grandes
- Java: escala Mapsforge Map al usar mosaicos de mapa de bits en línea en lugar del renderizador sin conexión
- Crear un nuevo mapa de bits y dibujar nuevos píxeles en él
- Cómo crear relieve alrededor de un mapa de bits?
- Cómo rellenar gridview con la imagen seleccionada de la galería o capturada desde la cámara
- "No se pueden dibujar mapas de bits reciclados" con Picasso
- ¿Cómo recortar el mapa de bits del área seleccionada en el lienzo?
- ¿Cómo puedo convertir el mapa de bits de Android a formato de color NV12?
Su buena práctica para coger una vez y dar a decodeFile
otra oportunidad. System.gc()
y llame a System.gc()
y pruebe a descodificar de nuevo. Existe una alta probabilidad de que funcione después de llamar a System.gc()
.
try { BitmapFactory.Options options = new BitmapFactory.Options(); options.inSampleSize = 4; bitmap = BitmapFactory.decodeFile(file, options); } catch (OutOfMemoryError e) { e.printStackTrace(); System.gc(); try { bitmap = BitmapFactory.decodeFile(file); } catch (OutOfMemoryError e2) { e2.printStackTrace(); // handle gracefully. } }
Hice algo como esto: coger el error sólo para tratar de reducir la imagen hasta que funcione. Eventualmente no puede trabajar en absoluto; Entonces devuelve null; De lo contrario, en caso de éxito, devuelve el mapa de bits.
Fuera, decido qué hacer con el mapa de bits si es nulo o no.
// Let w and h the width and height of the ImageView where we will place the Bitmap. Then: // Get the dimensions of the original bitmap BitmapFactory.Options bmOptions= new BitmapFactory.Options(); bmOptions.inJustDecodeBounds= true; BitmapFactory.decodeFile(path, bmOptions); int photoW= bmOptions.outWidth; int photoH= bmOptions.outHeight; // Determine how much to scale down the image. int scaleFactor= (int) Math.max(1.0, Math.min((double) photoW / (double)w, (double)photoH / (double)h)); //1, 2, 3, 4, 5, 6, ... scaleFactor= (int) Math.pow(2.0, Math.floor(Math.log((double) scaleFactor) / Math.log(2.0))); //1, 2, 4, 8, ... // Decode the image file into a Bitmap sized to fill the View bmOptions.inJustDecodeBounds= false; bmOptions.inSampleSize= scaleFactor; bmOptions.inPurgeable= true; do { try { Log.d("tag", "scaleFactor: " + scaleFactor); scaleFactor*= 2; bitmap= BitmapFactory.decodeFile(path, bmOptions); } catch(OutOfMemoryError e) { bmOptions.inSampleSize= scaleFactor; Log.d("tag", "OutOfMemoryError: " + e.toString()); } } while(bitmap == null && scaleFactor <= 256); if(bitmap == null) return null;
Por ejemplo, con una imagen de 3264×2448, el bucle itera 2 veces en mi teléfono, y luego funciona.
Desea atraparlo si desea mostrar una imagen más pequeña / una imagen diferente / mostrar un mensaje de error personalizado al usuario. Su contenedor de acceso a imágenes puede detectar estos errores y devolver algunos códigos de error personalizados definidos en su código; Su actividad que utiliza este código puede decidir qué hacer con el código de error – advertir al usuario, forzarlo a salir con un mensaje de error mejor que el que proporcionaría el sistema android, etc.
Btw, no está utilizando la variable de opciones en su código de ejemplo.
Aunque puede que no sea una buena idea capturar OutOfMemoryError con try-catch. Pero, a veces no tienes opción, porque todos nosotros odiamos fallas en la aplicación. Entonces, lo que puedes hacer es
- Catch OutOfMemoryError utilizando try-catch
- Puesto que, después de este error, su actividad puede volverse inestable, reiníciela.
- Puede desactivar las animaciones para que el usuario no sepa que la actividad se reinicia.
- Usted puede poner algunos datos adicionales en la intención de saber que la aplicación se estrelló durante la ejecución anterior.
Cómo lo hice es:
try { //code that causes OutOfMemoryError } catch (Exception e) { // in case of exception handle it e.printStackTrace(); } catch (OutOfMemoryError oome) { //restart this activity Intent i=this.getIntent(); i.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION); //disable animation //EXTRA_ABNORMAL_SHUTDOWN is user defined i.putExtra(this.EXTRA_ABNORMAL_SHUTDOWN, true); //put extra data into intent if you like finish(); //and finish the activity overridePendingTransition(0, 0); startActivity(i); //then start it(there is also restart method in newer API) return false; }
Y luego en onCreate of Activity puedes reanudar (algo como esto):
boolean abnormalShutdown=getIntent().getBooleanExtra(this.EXTRA_ABNORMAL_SHUTDOWN, false); if (abnormalShutdown) { //Alert user for any error //get any extra data you put befor restarting. }
Este enfoque salvó mi aplicación. Espero que te ayude también !!
- Ruta de construcción incompleta sólo en algunos espacios de trabajo (Android)
- Incorporación de ZXing en la aplicación de Android