Android利用缩放加载大图片避免内存溢出

因为安卓的堆内存有限(尽管现在随着安卓手机屏幕分辨率的提高堆内存没有以前小屏幕时代那么局限),要是完全加载一张大图片很容易导致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);
    	
    	
    }



还需注意的是,在dp.getWidth()与dp.getHeight()两个方法虽然显示已经过时,但是由于谷歌推荐的dp.getSize()只支持API leve 13的系统所以,由于加载图片为一项基础需求,所以需要支持低版本,我们还是继续用前两个方法。




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值