这是我参与11月更文挑战的第5天,活动详情查看:2021最后一次更文挑战
Bitmap加载图片
Bitmap在Android中通过BitmapFactory来实现加载图片资源。
BitmapFactory提供了四种形式加载Bitmap资源:decodeFile(文件), decodeResource(资源文件),decodeStream(输入流),decodeByteArray(字节数组)。
图片在Android中加载逻辑都在native底层实现,上面介绍的四种加载形式底层实现逻辑也都由以下方法实现。
一般情况下加载Bitmap不会加载图片的原始大小,小资源图片不会带来内存问题,但高清大图很容易导致OOM
造成应用闪退,因此BitmapFactory还有Options来控制加载Bitmap的尺寸大小从而实现图片高效加载。
BitmapFactory.Options
通过配置Options可以有效降低图片内存占用,有效减少图片展示造成的闪退问题。其中inSampleSize和inJustDecodeBounds是Options经常会使用到的两个参数。
- inSampleSize
设置图片缩放比,inSampleSize=1时表示图片大小为原始大小;inSampleSize大于1表示图片原始大小缩小,例如inSampleSize=2,100x100的图片缩小到50x50。而且inSampleSize是>=1的并没有放大功能。打个比方若拿一张1024x1024像素格式ARGB8888格式存储的图片,原图大小是4MB。通过inSampleSize设置2降低采样后512x512,压缩后大小是2MB,其压缩程度还是比较可观的。但同时也需要控制inSampleSize赋值,过大的压缩可能会导致图片失真。
- inJustDecodeBounds
inJustDecodeBounds也是比较重要的配置参数。当inJustDecodeBounds为true时获取到的只有图片的基本信息(宽,高,图片格式等),Bitmap对象是空的。这是因为解码过程值进行了图片信息的获取,并不加载图片资源。这样的轻量级操作不会造成OOM。使用inJustDecodeBounds常常用于对图片压缩前的前提操作,来获取图片信息后判断采取什么样的压缩策略。
下面代码就是常用的根据希望输出的destWidth,destHeight尺寸大小图片和原图原始尺寸做比较计算出inSampleSize得到最终图片。
Options opt = new Options();
opt.inJustDecodeBounds = true; /// 解码图片信息时设置为true
BitmapFactory.decodeResource(getResources(),"xxxxx",opt);
double scaleW = Math.max(destWidth, opt.outWidth) / (Math.min(destWidth, opt.outWidth) * 1.0);
double scaleH = Math.max(destHeight, opt.outHeight) / (Math.min(destHeight, opt.outHeight) * 1.0);
opt.inSampleSize = (int) Math.max(scaleW, scaleH);
opt.inJustDecodeBounds = false;/// 解码图片时设置为false
bitmap = BitmapFactory.decodeResource(getResources(),"xxxxx", opt); // 获取修改采样率后的图片
return bitmap;
总结
除了通过配置BitmapFactory.Options加载满足内存需求的图片,另外还有其他方式去压缩图片实现加载,例如质量压缩、缩放压缩、图片格式压缩等。通过更多压缩策略实现高效的图片加载。