首先 , 得明白什么是 OOM异常, 即OutOfMemory异常,内存溢出导致的.
1, 如何计算出 加载图片进内存时的大小?
在 Android中 , 加载一张图片时,比如 一张 2560X1920的高清图片,大小是 2560 x 1920 x 4 / 1024 / 1024 = 18.75 M,
android 中加载图片时,因为用的是argb处理, a 指透明度,r 指红色,g 指绿色, b 指蓝色,每个占8个bit即一个byte.所以,一个图片的像素是 4个字节.
2,为什么会出现 OOM异常?
上面已经计算出了图片加载进内存时的大小是 18.75 M,而我的这个模拟器上的虚拟机 的 堆内存 VM Heap只有 16M,所以就OOM了.
3,处理OOM 异常的方法。
处理OOM异常的方法有很多,我这里只列出最简单的一种
先介绍下思路 :
1,得到图片的宽和高
2,得到屏幕的宽和高(因为整个屏幕的像素都加载进内存,也不会造成内存溢出)
3,得到 图片的宽和屏幕宽(或控件宽)的比值,图片高和屏幕高(或控件高)的比值,选择比值大的那个
4,设置 Option的inSampleSize 属性来缩小图片
//这是一个按钮的点击事件,这样做的话,图片过大就会出现OOM异常
public void onClick(View view){
//在这一步,将图片加载进内存时,就已经出OOM了
Bitmap bitmap = BitmapFactory.decodeFile("/storage/sdcard/fury-006.jpg");
imageView.setImageBitmap(bitmap);
}
//处理后的情况则是
public void onClick(View v)
{
Options option = new Options();
/**如果该属性设为true的话,那么下面的decodeFile函数就会返回一个不带图片的bitmap对象,
* 并且,图片的实际宽高也会被映射到option对象中
*/
option.inJustDecodeBounds = true;
BitmapFactory.decodeFile("/storage/mnt/sdcard/fury-009.jpg", option);
//获得图片的实际宽高
int height = option.outHeight;
int width = option.outWidth;
//获得屏幕的宽高
WindowManager wm = this.getWindowManager();
int screen_height = wm.getDefaultDisplay().getHeight();
int screen_width = wm.getDefaultDisplay().getWidth();
//得到图片的宽高与屏幕或者ImageView控件大小的比值,选取合适的值
int scale = 1;
int sx = width/screen_width;
int sy = height/screen_height;
if(sx > sy && sx >= 1)
{
scale = sx;
}else if(sy > sx && sy >= 1)
{
scale = sy;
}
//如果该值设为false,那么就会返回带图片的Bitmap对象
option.inJustDecodeBounds = false;
option.inSampleSize = scale;//该值大于1的话,就会把图片按比例缩小,得到一个bitmap对象
Bitmap bitmap = BitmapFactory.decodeFile("/storage/sdcard/fury-009.jpg", option);
imageView.setImageBitmap(bitmap);
}
}