简体   繁体   English

高分辨率图像-OutOfMemoryError

[英]High resolution Image - OutOfMemoryError

I am developing an application for the Galaxy S4. 我正在为Galaxy S4开发一个应用程序。 One of the requirements of the application is having a SplashScreen containing an Image of 1920x1080 pixels. 该应用程序的要求之一是使SplashScreen包含1920x1080像素的图像。 Its a high quality .jpeg image and the size of the Image is about 2 Megabytes . 它是高质量的.jpeg图像,图像的大小约为2 MB

The problem is that I am getting an OutOfMemoryError as soon as I start the Application. 问题是,启动应用程序后,我立即收到OutOfMemoryError I am quite stunned that this already happens with an image of just 2 megabyte in size? 我很惊讶,这已经发生在只有2 MB大小的图像上了吗? How can I fix this problem and display the image? 如何解决此问题并显示图像?

Changing the dimensions or the size of the image is not an option. 不能更改图像的尺寸或大小。

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

And the splashscreen.xml 还有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"/>

ADDITIONAL INFORMATION: 附加信息:

Sometimes, (when a lot of device memory is available) the app is able to make it past the splash screen, but then, the memory consumption of the app is just insane . 有时,(当有大量设备内存可用时)该应用程序可以使其超过启动屏幕,但随后, 该应用程序的内存消耗简直是疯狂 (around 100 megabyte) . (大约100兆字节) Even though I close the SplashScreen Activity and finish() it, it seems that there is a reference to the ImageView / the Image kept in memory. 即使我关闭了SplashScreen Activity并完成了它的finish(),似乎仍然有对ImageView的引用/该图像保存在内存中。

How can I reduce the huge memory consumption? 如何减少巨大的内存消耗?

When I do not display the splash screen, my app only consumes around 35MB of memory. 当我不显示初始屏幕时,我的应用仅消耗大约35MB的内存。 With the SplashScreen image, its around 100MB. 使用SplashScreen图像时,其大小约为100MB。

Three hints which should help you: 三个提示可以帮助您:

  1. Use this to load your images, from Loading Large Bitmaps Android documentation : 加载大位图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. Make sure you have only one instance of your Bitmap in memory. 请确保你有你的只有一个实例Bitmap在内存中。 After displaying it, call recycle() and set your reference to null . 显示它之后,调用recycle()并将您的引用设置为null You can use Memory Allocation Tracker to see what is allocated. 您可以使用内存分配跟踪器查看分配的内容。 You can also read HPROF files, as suggested in comments. 您也可以按照注释中的建议阅读HPROF文件。

  3. By default ARGB_8888 pixel format is used, which means 4 bytes per pixel. 默认情况下使用ARGB_8888像素格式,这意味着每个像素4个字节。 Very good article: Bitmap quality, banding and dithering . 很好的文章: 位图质量,条纹和抖动 Your image is JPEG, so it doesn't have transparency, so you are wasting 1 byte on every pixel for alpha channel. 您的图片是JPEG,因此没有透明度,因此您在每个像素上浪费了1个字节作为alpha通道。 It's not very probable, but maybe with acceptable quality you can use even more economical format. 可能性不大,但是也许可以接受,但您可以使用更经济的格式。 Take a look at them. 采取一看他们。 Maybe RGB_565 for example. 例如RGB_565 It takes 2 bytes for pixel, so your image would be 50% lighter. 像素需要2个字节,因此您的图像会变亮50%。 You can enable dithering to improve the quality of RGB_565 . 您可以启用抖动以改善RGB_565的质量。

I had a similar problem and the solution is simple. 我有一个类似的问题,解决方案很简单。 Put your high resolution 1920x1080 px image in the drawable-nodpi directory. 将高分辨率的1920x1080 px图像放入drawable-nodpi目录中。 The system does not scale resources tagged with this qualifier regardless of the current screen's density, which leads to the OutOfMemoryError, so the problem should disappear. 无论当前屏幕的密度如何, 系统都不会缩放使用此限定符标记的资源 ,这会导致OutOfMemoryError,因此问题应消失。

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

Hope it helps. 希望能帮助到你。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM