BitmapFactory.decodeResource y inexplicable Fuera de memoria

Tengo un extraño fuera de error de memoria de decodificación de un recurso de imagen dibujable 960x926px jpg, la asignación de 3555856 byte. La imagen se coloca sólo en drawx-xxhdpi (3x) y estoy utilizando un dispositivo hdpi (1.5x). Dos preguntas:

¿Puede alguien explicarme?

NOTA: la pregunta es acerca de por qué obtener un OOM para asignar 3,5 MB mientras tiene 22,5 MB de memoria libre (consulte el registro)

03-18 17: 30: 15.050 32750-32750 /? D / dalvikvm: GC_FOR_ALLOC liberado 10809K, 49% libre 23735K / 46087K, pausado 89ms, total 89ms

03-18 17: 30: 15.050 32750-32750 /? I / dalvikvm-heap: Forzar la recopilación de SoftReferences para la asignación de 3555856 bytes

03-18 17: 30: 15.160 32750-32750 /? D / dalvikvm: GC_BEFORE_OOM liberado 29K, 49% libre 23705K / 46087K , pausado 103ms, total 103ms

03-18 17: 30: 15.160 32750-32750 /? E / dalvikvm-heap: Fuera de memoria en una asignación 3555856-byte .

03-18 17: 30: 15.160 32750-32750 /? I / dalvikvm: "main" prio = 5 tid = 1 RUNNABLE

03-18 17: 30: 15.160 32750-32750 /? I / dalvikvm: | Group = "main" sCount = 0 dsCount = 0 obj = 0x418fc6a0 auto = 0x4010c008

03-18 17: 30: 15.160 32750-32750 /? I / dalvikvm: | SysTid = 32750 nice = 1 sched = 0/0 cgrp = aplicaciones handle = 1075251280

03-18 17: 30: 15.160 32750-32750 /? I / dalvikvm: | Schedstat = (0 0 0) utm = 3807 stm = 859 core = 0

03-18 17: 30: 15.160 32750-32750 /? I / dalvikvm: en android.graphics.BitmapFactory.nativeDecodeAsset (Método nativo)

03-18 17: 30: 15.160 32750-32750 /? I / dalvikvm: en android.graphics.BitmapFactory.decodeStream (BitmapFactory.java:636)

03-18 17: 30: 15.160 32750-32750 /? I / dalvikvm: en android.graphics.BitmapFactory.decodeResourceStream (BitmapFactory.java:484) 03-18 17: 30: 15.160 32750-32750 /? I / dalvikvm: en android.graphics.BitmapFactory.decodeResource (BitmapFactory.java:512)

03-18 17: 30: 15.160 32750-32750 /? I / dalvikvm: en android.graphics.BitmapFactory.decodeResource (BitmapFactory.java:542)

5 Solutions collect form web for “BitmapFactory.decodeResource y inexplicable Fuera de memoria”

1) Si no tiene una versión más pequeña en la carpeta hdpi, utilizará la coincidencia más cercana. Por lo tanto, utilizará el xxhdpi si no hay hdpi o drawable / versión.

2) No autoscale. Se leerá en el tamaño completo.

3) Si esto causa un MOO, es probable que esté usando demasiada memoria en general.

La razón por la que está recibiendo MOO es porque cuando la imagen se decodifica en la memoria de su mapa de bits toma más tamaño que la resolución de la imagen (casi 4 veces no estoy seguro acerca de este valor).

Pocos puntos a tener en cuenta al trabajar con imágenes:

  1. Nunca maneje bitmaps en el hilo principal. Hacer toda la decodificación en segundo plano.
  2. Siempre considere el tamaño de la pantalla o el tamaño de la vista en la que va a colocar la imagen. Por ejemplo, si el tamaño de la pantalla es 360X720 (un valor aleatorio), entonces no es una buena idea decodificar una imagen de resolución completa que tenga una resolución mayor que el tamaño requerido (ya que cargará un mapa de bits completo en la memoria principal). Así que siempre muestreamos mientras decodificamos.

Así que trate de usar la siguiente solución:

Paso 1: Encuentre el tamaño de la pantalla

Tomado de aquí

Display display = getWindowManager().getDefaultDisplay(); Point size = new Point(); display.getSize(size); int width = size.x; int height = size.y; 

Paso 1: Crear una tarea asíncrona para decodificar mapa de bits

Si está utilizando la tarea asíncrona como clase interna, considere la posibilidad de utilizar una clase interna pública estática (para guardar problemas de pérdida de memoria) y mantener la referencia débil de la vista de imagen en la que se va a cargar la imagen. También pasa el recurso de imagen o el archivo o el flujo lo que quieras decodificar al constructor. En el siguiente código, supongamos que desea decodificar un recurso. También pase el ancho y la altura calculados en el paso 1.

 public static class BitmapDecodeTask extends AsyncTask<Void, Void, Bitmap> { //the reason to use a weak reference is to protect from memory leak issues. private WeakReference<Context> mContextReference; private WeakReference<ImageView> mImageViewReference; private int mResourceId; private int mRequiredWidth; private int mRequiredHeight; public BitmapDecodeTask(Context context, ImageView imageView, int resourceId, int width, int height) { this.mContextReference = new WeakReference<>(context); this.mImageViewReference = new WeakReference<>(imageView); this.mResourceId = resourceId; this.mRequiredWidth = width; this.mRequiredHeight = height; } @Override protected Bitmap doInBackground(Void... params) { Context context = mContextReference.get(); if(context != null) { BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeResource(getResources(), mImageResourceId, options); //set inSampleSize options.inSampleSize = calculateInSampleSize(options); //set inJustDecodeBounds = false; options.inJustDecodeBounds = false; //decode return BitmapFactory.decodeResource(getResources(), mImageResourceId, options); } return null; } @Override protected void onPostExecute(Bitmap bitmap) { //check if imageview is available or not ImageView imageView = mImageViewReference.get(); if(imageView != null && bitmap != null) { imageView.setImageBitmap(bitmap); } } public static int calculateInSampleSize(BitmapFactory.Options options) { // Raw height and width of image final int height = options.outHeight; final int width = options.outWidth; int inSampleSize = 1; if (height > mRequiredHeight || width > mRequiredWidth) { final int halfHeight = height / 2; final int halfWidth = width / 2; // Calculate the largest inSampleSize value that is a power of 2 and keeps both // height and width larger than the requested height and width. while ((halfHeight / inSampleSize) > mRequiredHeight && (halfWidth / inSampleSize) > reqWidth) { inSampleSize *= 2; } } return inSampleSize; } } 

Referencias:

Mapas de bits

El tamaño en la memoria del mapa de bits es anchura x altura x bits por color. Creo que no ha utilizado ninguna opción en particular, su está utilizando 4 bytes por píxel (Rojo 1 byte, Verde 1 byte, Azul 1 byte, Alpha 1 byte). Por lo tanto: 960 * 926 * 4 = 3555840 bytes.

Acerca de su OOM: lo que no parece tan habitual para mí es:

Forzar la colección de SoftReferences para la asignación de 3555856 bytes

¿Dónde almacena el mapa de bits asignado? Las referencias suaves deben evitarse en Android.

Pasando por la sugerencia de Gabe Sechan, recomendaría el uso de un sitio web como makeappicon , que le permite escalar cualquier imagen que es demasiado grande automáticamente. Es una herramienta útil, aunque Android debe manejar los problemas de escala para usted.

Mimmo Grottoli tiene razón sobre los bytes de ARGB, así que no hay nada de que preocuparse allí hasta donde yo pueda decir.

La razón por la que es más probable obtener este error es debido a una fuga de memoria importante involucrados en la creación (y no destruir) bitmaps, que aprendí la manera dura de un proyecto de steg hace un tiempo.

Para limpiar esta memoria, puede anular el método onDestroy() para su Actividad / Fragmento, o hacerlo manualmente cuando sea necesario.

 @Override public void onDestroy() { yourbitmap.recycle(); yourbitmap = null; super.onDestroy(); } 

Espero que el suyo fue útil para usted.

Es mejor utilizar bibliotecas como Glide o picasso para todas las operaciones de imagen (descodificación, redimensionamiento, descarga, etc.):

Reemplazar la ruta con la ruta de la carpeta local o la URL del servidor

Dependencia : compile 'com.github.bumptech.glide: glide: 3.5.2'

 Glide.with (context).load (path).asBitmap().into(imageView); 
  • Xamarin forma la imagen de Android no se está comprimiendo
  • BitmapFactory.decodeStream de Activos devuelve null en Android 7
  • Java.lang.OutOfMemoryError en android.graphics.BitmapFactory.decodeResource (BitmapFactory.java:374)
  • ¿Hay una manera de fijar el backgound de la barra de acción por la imagen en androide?
  • Tamaño de MediaStyle LargeIcon
  • Android BitmapFactory devolver null en Base64 decodificó byte matriz
  • Android cómo escalar una imagen con las opciones de BitmapFactory
  • Android PNG a Bitmap - SkImageDecoder :: Factory devuelto null
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.