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

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

  1. Catch OutOfMemoryError utilizando try-catch
  2. Puesto que, después de este error, su actividad puede volverse inestable, reiníciela.
  3. Puede desactivar las animaciones para que el usuario no sepa que la actividad se reinicia.
  4. 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 !!

  • Cargar imagen grande del servidor en Android
  • Cambiar el tamaño del mapa de bits de InputStream
  • Problema de conversión de URI a Bitmap (2014):
  • Sqlite Database - ¿Cómo guardar la imagen tomada de la intención de la cámara, así como hashmap a sqlite para recuperar más tarde?
  • Android: crear imagen circular con picasso
  • Creación eficiente de mapa de bits para marcadores de mapa
  • Cómo recortar mapa de bits con una ruta de acceso
  • Obtener coordenadas reales de xy de los usuarios
  • ¿Hay lejos para conseguir uri del mapa de bits con hacia fuera excepto él a sdcard?
  • MediaStore.Images.Media.getBitmap y fuera de error de memoria
  • Android: Bitmap: ¿Cómo guardar el lienzo con fondo verde en android?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.