高分辨率Image – OutOfMemoryError
我正在开发Galaxy S4的应用程序。 应用程序的要求之一是有一个包含1920×1080像素图像的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"/>
附加信息:
有时,(当有大量的设备内存可用)应用程序能够超过启animation面,但是, 应用程序的内存消耗是疯了 。 (大约100兆字节) 。 即使我closures了SplashScreen Activity并完成()它似乎有一个ImageView /图像保存在内存中的引用。
我怎样才能减less巨大的内存消耗?
当我不显示启animation面时,我的应用程序只消耗大约35MB的内存。 使用SplashScreen图像,大约100MB。
三个应该帮助你的提示:
-
使用它来加载你的图像,从加载大的位图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; }
-
确保内存中只有一个
Bitmap
实例。 显示之后,调用recycle()
并将你的引用设置为null
。 您可以使用内存分配跟踪器查看分配的内容。 您也可以阅读HPROF文件,如评论中所build议的那样。 -
默认使用
ARGB_8888
像素格式,即每个像素4字节。 非常好的文章: 位图质量,绑定和抖动 。 你的图像是JPEG,所以它没有透明度,所以你在每个alpha通道的像素上浪费了1个字节。 这不是很可能,但也许可以接受的质量,你可以使用更经济的格式。 看看他们。 也许RGB_565
例如。 它需要2个字节的像素,所以你的图像会轻50%。 您可以启用抖动来提高RGB_565
的质量。
我有一个类似的问题,解决scheme很简单。 把你的高分辨率的1920×1080像素图像放在drawable-nodpi目录中。 无论当前屏幕密度如何, 系统都不会缩放用此限定符标记的资源 ,这会导致OutOfMemoryError,所以问题应该消失。
请检查Android文档: http : //developer.android.com/intl/es/guide/practices/screens_support.html
希望它有帮助。