Qué tamaño almacenar imagen en el servidor para utilizar con la aplicación de Android

Tengo una aplicación de Android que permite al usuario subir fotos de perfil. Se almacenan 300px X 300px en el servidor.

En la aplicación, los uso en 40dp X 40dp o en ocasiones 100dp X 100dp. Las imágenes de 40dp están en ListView . En realidad, utilizo un LazyList terceros muy popular para almacenar las imágenes (usando una clase ImageLoader ) en un caché. Aquí está la biblioteca exacta .

Simplemente muestro la imagen en mi adapter como este:

 imageLoader.DisplayImage(profileUrl, holder.iv1); 

Tomo la URL de la web y la muestro directamente en ImageView 40dp x 40dp.

A veces me doy cuenta de la degradación de la imagen. Donde la imagen se carga parcialmente, entonces está dañada.

Una teoría es que el ir de una imagen grande en el servidor y tratar de almacenarla en un área pequeña en la aplicación real, a continuación, hacer esto muchas veces en un ListView , está causando algunos problemas de carga.

La pregunta: ¿Cuál es la mejor manera de manejar esta situación cuando tienes una imagen mucho más grande en el servidor de lo que necesitas mostrar? Estoy asumiendo que puede necesitar utilizar BitMapFactory o una clase similar para construir una nueva imagen. Pero no estoy seguro. Siento que me falta un paso.

He aquí un ejemplo de una imagen en un ListView que se ha corrompido, observe que esto no le sucede a todos. (Y sí que es Tobías de Arrested Development .)

Seguimiento : ¿Y cómo tomamos en consideración el tamaño de archivo para xxhdpi , xhdpi , etc, cuando la imagen viene del servidor y no la carpeta de recursos?

Introduzca aquí la descripción de la imagen

La biblioteca que está utilizando parece que apenas se mantiene (la última actualización tiene al menos un año de antigüedad). Hay varias bibliotecas nuevas y probablemente mejores que resuelven el mismo problema. Mi favorito es Square's Picasso . Es muy sencillo de usar y soluciona muy bien la carga de imágenes dentro de un problema ListView.

Para responder más directamente a algunas de sus preguntas:

¿Cuál es la mejor manera de manejar esta situación cuando tienes una imagen mucho más grande en el servidor que necesitas mostrar?

Necesita subamplear el mapa de bits hasta el tamaño de destino. Google tiene una muy buena escribir sobre todo esto aquí .

Primero tienes que decodificar el bitmap estableciendo el booleano inJustDecodeBounds para obtener el tamaño del mapa de bits.

 BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeResource(getResources(), R.id.myimage, options); int imageHeight = options.outHeight; int imageWidth = options.outWidth; String imageType = options.outMimeType; 

A continuación, puede calcular el tamaño de la muestra en función de la altura y el ancho de su objetivo.

 public static int calculateInSampleSize( BitmapFactory.Options options, int reqWidth, int reqHeight) { // Raw height and width of image final int height = options.outHeight; final int width = options.outWidth; int inSampleSize = 1; if (height > reqHeight || width > reqWidth) { 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) > reqHeight && (halfWidth / inSampleSize) > reqWidth) { inSampleSize *= 2; } } return inSampleSize; } 

A continuación, puede utilizar el tamaño de muestra calculado para cargar el mapa de bits muestreado. El código final sería algo así como

 public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, int reqWidth, int reqHeight) { // First decode with inJustDecodeBounds=true to check dimensions final BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; BitmapFactory.decodeResource(res, resId, options); // Calculate inSampleSize options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight); // Decode bitmap with inSampleSize set options.inJustDecodeBounds = false; return BitmapFactory.decodeResource(res, resId, options); } 

¿Y cómo tomamos en consideración el tamaño de archivo para xxhdpi, xhdpi, etc, cuando la imagen viene del servidor y no la carpeta de recursos?

Puede calcular el tamaño de píxeles objetivo que desea reducir el tamaño de su mapa de bits mediante el siguiente fragmento:

 float pixels = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, "10", context.getResources().getDisplayMetrics()); 

TL, DR

Utilice el Picasso de Square y resolverá todos sus problemas.

Sugiero agregar un argumento a la URL que utilizas para solicitar la imagen (por ejemplo, &size=small ) y hacer que tu servidor mantenga varios tamaños de cada imagen. Algunos beneficios a esto son:

  1. Menor uso de datos de la aplicación
  2. Mejor calidad de imagen (no tener que volver a muestrear el iamge)
  3. Mejor rendimiento (los mapas de bits grandes tardan mucho más en cargarse)

Los inconvenientes son:

  1. Más complejidad (lógica para determinar qué tamaño solicitar)
  2. Más requisitos de almacenamiento en el servidor

Creo que los profesionales superan con creces los contras, y usted terminará con una experiencia de usuario mucho mejor.

Para su seguimiento, usted podría incluso tener argumentos para cada densidad (por ejemplo, &density=mdpi ) que serviría el tamaño apropiado (y podría simplemente cambiar getResources().getDisplayMetrics().densityDpi para obtener el valor del argumento).

Por ejemplo:

 int densityDpi = getResources().getDisplayMetrics().densityDpi; if (densityDpi <= DisplayMetrics.DENSITY_MEDIUM) { return "mdpi"; } else if (densityDpi <= DisplayMetrics.DENSITY_HIGH) { return "hdpi"; } else if (densityDpi <= DisplayMetrics.DENSITY_XHIGH) { return "xhdpi"; } else if (densityDpi <= DisplayMetrics.DENSITY_XXHIGH) { return "xxhdpi"; } else { return "xxxhdpi"; } 
  • Convierta la matriz de bytes NV21 en formato legible de mapa de bits
  • Recorte de rectángulo redimensionable de Android
  • Tamaño de pantalla de Android Scaling Canvas
  • Obtención de mapa de bits desde SurfaceView personalizado
  • Android: actualiza el mapa de bits del hilo del temporizador
  • Android - efecto de deformación de imagen
  • Cómo devolver el mapa de bits de la actividad secundaria en android
  • ¿Por qué estoy recibiendo java.io.IOException: Mark ha sido invalidado?
  • La compresión de mapa de bits de Android no es buena
  • Imagen de Facebook como icono grande La notificación aparece en blanco en diferentes teléfonos?
  • Dibujo androide en evento táctil
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.