Android: la memoria caché de bitmap requiere mucha memoria

Soy nuevo en todo el tema de administración de memoria, por lo que hay muchas cosas que no entiendo.
Intento almacenar en caché una imagen en mi aplicación, pero estoy teniendo problemas con su consumo de memoria:

Todo el código de Bitmap Chaching está prácticamente copiado desde aquí: http://developer.android.com/training/displaying-bitmaps/index.html

Depuré el código y verifiqué el tamaño del montón en la vista DDMS en eclipse, y hay aproximadamente 15 MB de salto después de estas líneas de código:

options.inJustDecodeBounds = false; return BitmapFactory.decodeResource(res, resId, options); 

en el método “decodeSampledBitmapFromResource”.

La imagen es un archivo jpg de 1024×800, 75kb. Según lo que ya he visto en Internet, la cantidad de memoria que se supone que debe tomar esta imagen es de aproximadamente 1024 * 800 * 4 (Bytes por píxel) = 3.125mb

Todos los hilos con respecto a este tema no dicen por qué se está tomando mucha más memoria de la que debería. ¿Hay alguna forma de almacenar en caché una imagen con una cantidad razonable de memoria?

EDITAR

Intenté usar el método decodeFile sugerido en la respuesta de @ArshadParwez a continuación. Usando este método, después del método BitmapFactory.decodeStream, la memoria se incrementa solo en 3.5mb – problema resuelto, más o menos, pero quiero almacenar mapas de bits directamente desde el recurso.

Observé que durante el método decodeResource hay 2 “saltos” de memoria, uno de aproximadamente 3.5mb, que es razonable, y otro extraño de 14mb. ¿Para qué se usan esos 14mb y por qué sucede esto?

Las imágenes también se escalan según la densidad para que puedan usar mucha memoria.

Por ejemplo, si el archivo de imagen está en la carpeta mdpi (que es densidad mdpi ) y lo ejecuta en un dispositivo xhdpi , tanto el ancho como el alto se duplicarían. Tal vez este enlace podría ayudarte, o este .

Entonces, en tu ejemplo, los bytes que tomaría el archivo de imagen son:

(1024 * 2) * (800 * 2) * 4 = 13,107,200 bytes.

Sería aún peor si lo ejecutara en un dispositivo xxhdpi (como el HTC one y el Galaxy S4).

¿Qué puedes hacer? Coloque el archivo de imagen en la carpeta de densidad correcta ( drawable-xhdpi o drawable-xhdpi drawable-xxhdpi ) o póngalo en drawable-nodpi (o en la carpeta de activos) y reduzca la escala de la imagen según sus necesidades.

Por cierto, no tiene que establecer options.inJustDecodeBounds = false ya que es el comportamiento predeterminado. De hecho, puede establecer nulo para las opciones de bitmap.

Acerca de la reducción de escala, puede usar la forma de google o la forma en que cada uno tiene sus propias ventajas y desventajas.

Acerca del almacenamiento en caché hay muchas maneras de hacerlo. El más común es el caché LRU. También hay una alternativa que he creado recientemente (enlace aquí o aquí ) que te permite almacenar en caché muchas más imágenes y evitar tener OOM, pero te da mucha responsabilidad.

Puede usar este método para pasar la imagen y obtener un bitmap de ella:

 public Bitmap decodeFile(File f) { Bitmap b = null; try { // Decode image size BitmapFactory.Options o = new BitmapFactory.Options(); o.inJustDecodeBounds = true; FileInputStream fis = new FileInputStream(f); BitmapFactory.decodeStream(fis, null, o); fis.close(); int IMAGE_MAX_SIZE = 1000; int scale = 1; if (o.outHeight > IMAGE_MAX_SIZE || o.outWidth > IMAGE_MAX_SIZE) { scale = (int) Math.pow( 2, (int) Math.round(Math.log(IMAGE_MAX_SIZE / (double) Math.max(o.outHeight, o.outWidth)) / Math.log(0.5))); } // Decode with inSampleSize BitmapFactory.Options o2 = new BitmapFactory.Options(); o2.inSampleSize = scale; fis = new FileInputStream(f); b = BitmapFactory.decodeStream(fis, null, o2); fis.close(); } catch (IOException e) { e.printStackTrace(); } return b; } 

@Ori Wasserman: De acuerdo con su solicitud, utilicé un método para obtener imágenes de la carpeta de recursos y también utilicé una imagen de 7 MB. Puse la imagen de 7 MB en la carpeta “res-> drawable” y con el siguiente código no se colgó y la imagen se mostró en la vista de imagen:

  Bitmap image = BitmapFactory.decodeResource(getResources(), R.drawable.image_7mb); loBitmap = Bitmap.createScaledBitmap(image, width_of_screen , height_of_screen, true); imageview.setImageBitmap(loBitmap);