高分辨率图像 - OutOfMemoryError

时间:2013-08-22 15:53:54

标签: android image bitmap android-imageview out-of-memory

我正在为Galaxy S4开发一个应用程序。 该应用程序的一个要求是使用包含 1920x1080 像素的图像的SplashScreen。它是一个高质量的.jpeg图像,图像的大小约为 2兆字节

问题是,一旦启动应用程序,我就会收到 OutOfMemoryError 。我很震惊,这已经发生了只有2兆字节的图像? 如何解决此问题并显示图片?

  

不能选择更改图像的尺寸或尺寸。

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

以及splashscreen.xml

    <ImageView 
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/ivSplashScreenImage"
        android:layout_width="match_parent"
        android:layout_height="match_parent" 
        android:scaleType="fitXY"
        android:src="@drawable/high_res_splashscreen_image"/>

其他信息:

有时,(当有大量设备内存可用时)应用程序可以通过启动画面,但是,应用程序的内存消耗只是疯狂(约100兆字节)。即使我关闭SplashScreen活动并完成()它,似乎对ImageView /图像保留在内存中的引用。

如何减少巨大的内存消耗?

  

当我不显示启动画面时,我的应用程序仅消耗大约35MB   记忆使用SplashScreen图像,大约100MB。

2 个答案:

答案 0 :(得分:14)

可以帮助您的三个提示:

  1. 使用此功能从Loading Large Bitmaps Android documentation

    加载图片
    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. 确保内存中只有Bitmap的一个实例。显示后,请致电recycle()并设置您对null的引用。您可以使用Memory Allocation Tracker查看分配的内容。您还可以按照注释中的建议阅读HPROF文件。

  3. 默认使用ARGB_8888像素格式,即每像素4个字节。非常好的文章:Bitmap quality, banding and dithering。您的图像是JPEG,因此它没有透明度,因此您在Alpha通道的每个像素上浪费1个字节。这可能不太可能,但可能具有可接受的质量,您可以使用更经济的格式。 Take看看他们。也许RGB_565例如。像素需要2个字节,因此您的图像将减轻50%。您可以启用抖动以提高RGB_565的质量。

答案 1 :(得分:6)

我有类似的问题,解决方案很简单。将高分辨率1920x1080像素图像放在 drawable-nodpi 目录中。 系统不会缩放使用此限定符标记的资源,无论当前屏幕的密度如何,都会导致OutOfMemoryError,因此问题应该消失。

请查看Android文档:http://developer.android.com/intl/es/guide/practices/screens_support.html

希望它有所帮助。