¿Qué hay de malo en este método de cálculo inSampleSize para Bitmaps? Sin memoria

En mi aplicación estoy iterando a través de URL de imágenes, la decodificación y ponerlos en un ArrayList<Bitmap> .

Pueden variar mucho en tamaño, por lo que estoy haciendo un "pre-decodificar" con la opción inJustDecodeBounds = true para calcular el valor inSampleSize necesario para la decodificación real.

Ver mi método para esto abajo, espero que no sea demasiado difícil de entender. Básicamente estoy apuntando para un tamaño similar al tamaño de la pantalla del dispositivo.

 for (Element e: posts) { if (!e.id().equals("")) { //preparing decode options = new BitmapFactory.Options(); input = new URL(e.url).openStream(); options.inJustDecodeBounds = true; BitmapFactory.decodeStream(input, null, options); input.close(); //setting inSampleSize if necessary int picPixels = options.outWidth * options.outHeight; int picScreenRatio = picPixels / screenPixels; if (picScreenRatio > 1) { int sampleSize = picScreenRatio % 2 == 0 ? picScreenRatio : picScreenRatio + 1; options.inSampleSize = sampleSize; } //actual decode input = new URL(e.url).openStream(); options.inJustDecodeBounds = false; Bitmap pic = BitmapFactory.decodeStream(input, null, options); input.close(); picList.add(pic); } } 

Código para calcular screenPixels :

 Display display = getWindowManager().getDefaultDisplay(); Point screenSize = new Point(); display.getSize(screenSize); int screenPixels = screenSize.x * screenSize.y; 

Estoy pasando por ~ 60 imágenes y alrededor de 40 mi aplicación se bloquea con java.lang.OutOfMemoryError .

Como entiendo, con inJustDecodeBounds = true no hay memoria asignada, y si mi método es correcto (creo que lo es), imágenes muy grandes obtener inSampleSize s muy grande, por lo que no sé cuál podría ser el problema.

Apreciaría cualquier consejo.

No importa que use inSampleSize no puede tener fácilmente 60 mapas de bits tan grandes como su pantalla en la memoria.

Asumiendo una pantalla fullhd obtendrá alrededor de 1920*1080*60*4 bytes.

Eso es aproximadamente 500 MB de datos . Debe cambiar de alguna manera su lógica de carga de mapa de bits.

En esta respuesta puede averiguar cuánta memoria puede contar. Difiere para varios dispositivos.

Pero siempre trate de hacer que la aplicación como memoria eficiente como sea posible.

El tamaño de la muestra debe ser una potencia de dos. De la documentación:

Si se establece en un valor> 1, solicita al decodificador que submuestre la imagen original, devolviendo una imagen más pequeña para guardar la memoria. El tamaño de la muestra es el número de píxeles en cada dimensión que corresponden a un único píxel en el mapa de bits decodificado. Por ejemplo, inSampleSize == 4 devuelve una imagen que es 1/4 del ancho / alto del original y 1/16 del número de píxeles. Cualquier valor <= 1 se trata igual que 1. Nota: el decodificador utiliza un valor final basado en potencias de 2, cualquier otro valor se redondeará a la potencia de 2 más próxima.

Aquí está un buen truco de la biblioteca de Android – Volley sobre cómo encontrar el mejor tamaño de muestra para mapas de bits:

  int findBestSampleSize(int actualWidth, int actualHeight, int desiredWidth, int desiredHeight) { double wr = (double) actualWidth / desiredWidth; double hr = (double) actualHeight / desiredHeight; double ratio = Math.min(wr, hr); float n = 1.0f; while ((n * 2) <= ratio) { n *= 2; } return (int) n; } 

Es notoriamente difícil conseguir la manipulación de imágenes directamente en Android. Yo recomendaría que utilice una biblioteca de administración de imágenes establecida como Fresco de Facebook :

https://github.com/facebook/fresco

Un ejemplo de sus documentos:

Los dibujos de Fresco muestran un marcador de posición para usted hasta que la imagen se ha cargado y mostrar automáticamente a la imagen cuando llega. Cuando la imagen sale de la pantalla, libera automáticamente su memoria.

También:

Las aplicaciones que utilizan Fresco pueden ejecutarse incluso en dispositivos de gama baja sin tener que luchar constantemente para mantener su huella de memoria de imagen bajo control.

  • Convertir Bitmap a Byte matriz SIN Bitmap.CompressFormat
  • ¿Es posible utilizar el método BitmapFactory.decodeFile para decodificar una imagen desde la ubicación http?
  • Cargar muchas imágenes de mapa de bits grandes como miniaturas - Android
  • ¿Cuál es la unidad de bitmap.getWidth () o bitmap.getHeight ()
  • Convertir todos los colores distintos de un color en particular en un mapa de bits a blanco
  • ALPHA_8 bitmaps y getPixel
  • Obtener el tamaño de Bitmap Android
  • PackageManager.getApplicationIcon () devolver el icono predeterminado?
  • Cómo ver realmente un mapa de bits tomado de un volcado de montón de Android
  • Superposición de color en android NDK
  • ¿Por qué setImageBitmap no tiene efecto en ImageButton personalizado?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.