Hochauflösendes Bild – OutOfMemoryError

Ich entwickle eine Anwendung für das Galaxy S4. Eine der Anforderungen der Anwendung ist ein SplashScreen mit einem Bild von 1920×1080 Pixeln. Es ist ein qualitativ hochwertiges .jpeg Bild und die Größe des Bildes beträgt etwa 2 Megabyte .

Das Problem ist, dass ich einen OutOfMemoryError bekomme , sobald ich die Anwendung starte . Ich bin ziemlich verblüfft, dass dies bereits bei einem Bild von nur 2 Megabyte Größe passiert? Wie kann ich dieses Problem beheben und das Bild anzeigen?

Ändern der Abmessungen oder der Größe des Bildes ist keine Option.

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(); } } 

Und die Splashscreen.xml

   

ZUSÄTZLICHE INFORMATION:

Manchmal (wenn viel Gerätespeicher verfügbar ist) ist die App in der Lage, den Begrüßungsbildschirm zu verlassen, aber dann ist der Speicherverbrauch der App einfach verrückt . (etwa 100 Megabyte) . Obwohl ich die SplashScreen-Aktivität schließe und es beende (), scheint es einen Verweis auf das ImageView / das Bild im Speicher zu geben.

Wie kann ich den enormen Speicherverbrauch reduzieren?

Wenn der Begrüßungsbildschirm nicht angezeigt wird, verbraucht meine App nur ca. 35 MB Speicher. Mit dem SplashScreen-Bild sind es rund 100 MB.

    Drei Hinweise, die dir helfen sollten:

    1. Verwenden Sie dies, um Ihre Bilder zu laden, wenn Sie die Android-Dokumentation Loading Large Bitmaps laden:

       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. Stellen Sie sicher, dass nur eine Instanz Ihrer Bitmap im Speicher vorhanden ist. Rufen Sie nach dem Anzeigen recycle() und setzen Sie Ihre Referenz auf null . Sie können den Speicherzuordnungsverfolger verwenden, um zu sehen, was zugewiesen ist. Sie können HPROF-Dateien auch lesen, wie in Kommentaren vorgeschlagen.

    3. Standardmäßig wird das ARGB_8888 Pixelformat verwendet, was 4 Bytes pro Pixel bedeutet. Sehr guter Artikel: Bitmap-Qualität, Banding und Dithering . Ihr Bild ist JPEG, also hat es keine Transparenz, deshalb verschwenden Sie 1 Byte auf jedem Pixel für den Alphakanal. Es ist nicht sehr wahrscheinlich, aber vielleicht mit akzeptabler Qualität können Sie ein noch sparsameres Format verwenden. Schau sie dir an. Vielleicht RGB_565 zum Beispiel. Es dauert 2 Bytes für Pixel, so dass Ihr Bild 50% leichter wäre. Sie können Dithering aktivieren, um die Qualität von RGB_565 zu verbessern.

    Ich hatte ein ähnliches Problem und die Lösung ist einfach. Stellen Sie das Bild mit der hohen Auflösung von 1920×1080 px in das Drawable-Nodpi- Verzeichnis. Das System skaliert Ressourcen, die mit diesem Qualifikationsmerkmal versehen sind, unabhängig von der aktuellen Bildschirmdichte, die zum OutOfMemoryError führt, sodass das Problem verschwinden sollte.

    Bitte überprüfen Sie die Android Dokumentation: http://developer.android.com/intl/es/guide/practices/screens_support.html

    Ich hoffe es hilft.