Imagen de alta resolución – OutOfMemoryError

Estoy desarrollando una aplicación para el Galaxy S4. Uno de los requisitos de la aplicación es tener una SplashScreen que contenga una Imagen de 1920×1080 píxeles. Es una imagen .jpeg de alta calidad y el tamaño de la imagen es de aproximadamente 2 megabytes .

El problema es que obtengo un OutOfMemoryError tan pronto como comienzo la aplicación. Estoy bastante sorprendido de que esto ya ocurra con una imagen de solo 2 megabytes de tamaño. ¿Cómo puedo solucionar este problema y mostrar la imagen?

Cambiar las dimensiones o el tamaño de la imagen no es una opción.

SplashScreen.java

public class Splashscreen extends Activity { private static final int SPLASH_DURATION = 2000; private boolean isBackPressed = false; @Override protected void onCreate(Bundle savedInstanceState) { requestWindowFeature(Window.FEATURE_NO_TITLE); getWindow().setFlags(LayoutParams.FLAG_FULLSCREEN, LayoutParams.FLAG_FULLSCREEN); super.onCreate(savedInstanceState); setContentView(R.layout.splashscreen); Handler h = new Handler(); h.postDelayed(new Runnable() { @Override public void run() { // check if the backbutton has been pressed within the splash_duration if(!isBackPressed) { Intent i = new Intent(Splashscreen.this, MainActivity.class); i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP); Splashscreen.this.startActivity(i); overridePendingTransition(R.anim.short_fade_in, R.anim.short_fade_out); } finish(); } }, SPLASH_DURATION); } @Override public void onBackPressed() { isBackPressed = true; super.onBackPressed(); } } 

Y el splashscreen.xml

   

INFORMACIÓN ADICIONAL:

A veces, (cuando hay mucha memoria del dispositivo disponible), la aplicación puede pasar de la pantalla de inicio, pero el consumo de memoria de la aplicación es simplemente una locura . (alrededor de 100 megabytes) . Aunque cierro la actividad de SplashScreen y la termino (), parece que hay una referencia a ImageView / the Image guardado en la memoria.

¿Cómo puedo reducir el gran consumo de memoria?

Cuando no muestro la pantalla de presentación, mi aplicación solo consume alrededor de 35 MB de memoria. Con la imagen de SplashScreen, es alrededor de 100 MB.

Tres sugerencias que deberían ayudarte:

  1. Use esto para cargar sus imágenes, desde la documentación de Loading Big Bitmaps Android :

     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); } 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) { // Calculate ratios of height and width to requested height and width final int heightRatio = Math.round((float) height / (float) reqHeight); final int widthRatio = Math.round((float) width / (float) reqWidth); // Choose the smallest ratio as inSampleSize value, this will guarantee // a final image with both dimensions larger than or equal to the // requested height and width. inSampleSize = heightRatio < widthRatio ? heightRatio : widthRatio; } return inSampleSize; } 
  2. Asegúrese de tener solo una instancia de su Bitmap en la memoria. Después de mostrarlo, llame a recycle() y configure su referencia a null . Puede usar el seguidor de asignación de memoria para ver qué se asigna. También puede leer archivos HPROF, como se sugiere en los comentarios.

  3. De forma predeterminada, se utiliza el formato de píxel ARGB_8888 , lo que significa 4 bytes por píxel. Muy buen artículo: calidad de bitmap, bandas y ttwigdo . Su imagen es JPEG, por lo que no tiene transparencia, por lo que está desperdiciando 1 byte en cada píxel para el canal alfa. No es muy probable, pero tal vez con una calidad aceptable puede utilizar un formato aún más económico. Échales un vistazo. Quizás RGB_565 por ejemplo. Toma 2 bytes por píxel, por lo que su imagen sería un 50% más ligera. Puede habilitar el difuminado para mejorar la calidad de RGB_565 .

Tuve un problema similar y la solución es simple. Coloque su imagen de alta resolución de 1920×1080 px en el directorio drawable-nodpi . El sistema no escala los recursos etiquetados con este calificador, independientemente de la densidad de la pantalla actual, lo que lleva al OutOfMemoryError, por lo que el problema debería desaparecer.

Consulte la documentación de Android: http://developer.android.com/intl/es/guide/practices/screens_support.html

Espero eso ayude.