因为安卓的堆内存有限(尽管现在随着安卓手机屏幕分辨率的提高堆内存没有以前小屏幕时代那么局限),要是完全加载一张大图片很容易导致OOM(out of memory)的问题。
所以为了解决这一情况,我们可以通过缩放这一个方法来加载图片。
首先我们介绍今天要用到的API:BitmapFactory.Options
我们先上代码:
<span style="font-family:Microsoft YaHei;">//解析图片时需要使用到的参数封装在opt这个对象里
Options opt = new Options();
//不用为像素申请内存,只获取图片的宽高
opt.inJustDecodeBounds = ture;
BitmapFactory.decodeFile("sdcard/xx.jpg",opt);</span>
现在出现了一个新的东东,我们看一下API文档咋说。
If set to true,the decoder will return null(no bitmap),but the out... fields will still be st,allowing the caller to query the bitmap without having to allocate the memory for pixels.
意思是说,要是我们将opt.inJustDecodeBounds设为ture,这个解析器就不会返回图片,它只会返回图片的一些信息。这样子就可以使调用者可以请求图片,却不用分配内存
现在我们理清一下缩放图片的步骤:
1.用Options.inJustDecodeBounds来获取大图片的宽高
2.获取手机屏幕的分辨率
3.通过图片宽高与手机屏幕宽高得到一个缩放图片的比例
譬如:手机屏幕分辨率为1920x1080
大图片分辨率为5184x3456
5184/1920=2
3456/1080=3
(通常我们取整数作为缩放比例,然后为了最大程度避免OOM情况我们会选择一个较大的缩放比例,这里我们选择3,还要确保比例大于等于1)
4.设置缩放比例
5.把inJustDecodeBounds设为false(要是不设为false会出现图片不能解析,因为只会解析边界
6.Bitmap bm = BitmapFactory.decodeFile("sdcard/xx.jpg",opt) 解析缩放后的图片
public void click(View v){
//解析图片时的参数封装到这个对象里面
Options opt = new Options();
//只解析大图片的宽高信息,不用耗费内存解析图片像素
opt.inJustDecodeBounds = true;
//传入一个opt对象
BitmapFactory.decodeFile("sdcard/xx.jpg", opt);
//拿到大图片的宽高
int imageWidth = opt.outWidth;
int imageHeight = opt.outHeight;
Display dp = getWindowManager().getDefaultDisplay();
//获取屏幕宽高
int screenWidth = dp.getWidth();
int screenHeight = dp.getHeight();
//计算缩放比例
int scale = 1;
int scaleWidth = imageWidth / screenWidth;
int scaleHeight = imageHeight / screenHeight;
if(scaleHeight >= scaleWidth && scaleHeight >=1){
scale = scaleHeight;
}
else if(scaleWidth >= scaleHeight && scaleWidth >= 1){
scale = scaleWidth;
}
//设置缩放比例
opt.inSampleSize = scale;
opt.inJustDecodeBounds = false;
Bitmap bm = BitmapFactory.decodeFile("sdcard/xx.jpg", opt);
ImageView iv = (ImageView)findViewById(R.id.iv);
iv.setImageBitmap(bm);
}