Bitmap的加载

先看看这个异常:
java.lang.OutofMemoryErroe:bitmap size exceeds VM budget
在开发时常遇到,android对单个应用的内存限制在16MB,但是现在手机种类繁多,各个厂商不同的手机版本和型号有所不同分配的内存也不同。在加载Bitmap的时候很容易造成内存溢出。因此高效地加载Bitmap是一个很重要也很容易被我们忽视的问题。


在Android中Bitmap指的是一张图片,可以是png、jpg格式等常见的图片格式,如何加载一个Bitmap呢?
BitmapFactory类提供了四类方法:decodeFile、decodeStream、decodeResource、decodeByteArray,分别从文件系统,输入流,资源,字节数组中加载一个Bitmap对象,其中decodeFile和decodeResource又间接调用了decodeStream方法,这四类方法最终在android底层实现的。对应着BitmapFactory类的几个native方法。


高效的加载一个Bitmap需要采用BitmapFactory.options来加载所需尺寸的图片,开发中我们使用的控件往往没有(例如:ImageView)图片的原始尺寸那么大,这时把这个图片加载进来在设置给控件显然没必要,因为控件并没有办法显示原始图片。通过BitmapFactory.options就可以按一定的采样率加载缩小图片,将缩小后的图片在控件上显示,这样会降低内存占用在一定程度上避免OOM.


通过BitmapFactory.options来缩放图片,主要是用到它的inSampleSize参数,即采样率。inSampleSize的取值应该总是2的指数,例如 1、2、4、6、8、16、32……等。比如为2时,采样后的图片大小为原图大小1/2,而像素为原图的1/4,占有内存大小也为原图的1/4.拿一张1024*1024像素的图片来说,假定采用ARGB8888格式存储,那么它占用内存为1024*1024*4,即 4 MB,如果inSampleSize为2,那么采样后的图片内存占用只有512*512*4,即 1 MB,如果外界传递给系统的inSampleSize不为 2 的指数,那么系统会向下取整应选择一个最接近的 2 的指数代替,比如3,系统会选择2 来代替。但是这个结论并非在所有的android版本上都成立。因此只是一个开发建议。


通过采样率即可有效地加载图片,开发中我们如何获取采样率呢?
主要分四步:
1.将BitmapFactory.options的inJustDecodeBounds参数设为true,并加载图片。
2.从BitmapFactory.options中取出图片的原始宽高信息,这个操作是轻量级的,并不会真正去加载图片。它们对应于outWidth 和 outHeight参数。
3.根据采样率的规则并结合目标View的所需大小计算inSampleSize.
4.将BitmapFactory.options 的inJustDecodeBounds参数设为false,重新加载图片。
将上面的4个流程用程序实现,代码:

public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, int reqWidth ,int reqHeight){
     final BitmapFactory.Options  options = new BitmapFactory.Options();
     options.inJustDecodeBounds = true;
     BitmapFactory.decodeResource(res,resId, options);
     //Calculate inSampleSize
     options.inSampleSize = calculateInSampleSize(options,reqWidth,reqHeight);
     options.inJustDecodeBounds = false;
     return BitmapFactory.decodeResource(res, resId,options);
}
public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight){
     final int height = options.outHeigth;
     final int width  = optiosn.outWidth;
     int inSampleSize = 1;
     if (height > reqHeight || width > reqWidth ){
         final int halfHeight  = height / 2;
         final int halfWidth   = width / 2;
         while((halfHeight / inSampleSize) >= reqHeight && (halfWidth / inSampleSize) >=reqWidth.){
             inSampleSize *=2;
         }
    }
    return inSampleSize;
}
我们在实际使用时就更简单了,比附ImageView所期望的图片大小为100*100像素,这个时候就可以通过如下方式高效加载并显示图片:
mImageView.stImageBitmap(decodeSampleBitmapFromResource(getResource(), R.id.icon,100,100));
BitmapFactory的四个方法都支持采样加载,并且处理方式类似。但是decodeStream方法稍微特殊。
(1)普通用户端(全平台) 音乐播放核心体验: 个性化首页:基于 “听歌历史 + 收藏偏好” 展示 “推荐歌单(每日 30 首)、新歌速递、相似曲风推荐”,支持按 “场景(通勤 / 学习 / 运动)” 切换推荐维度。 播放页功能:支持 “无损音质切换、倍速播放(0.5x-2.0x)、定时关闭、歌词逐句滚动”,提供 “沉浸式全屏模式”(隐藏冗余控件,突出歌词与专辑封面)。 多端同步:自动同步 “播放进度、收藏列表、歌单” 至所有登录设备(如手机暂停后,电脑端打开可继续播放)。 音乐发现与管理: 智能搜索:支持 “歌曲名 / 歌手 / 歌词片段” 搜索,提供 “模糊匹配(如输入‘晴天’联想‘周杰伦 - 晴天’)、热门搜索词推荐”,结果按 “热度 / 匹配度” 排序。 歌单管理:创建 “公开 / 私有 / 加密” 歌单,支持 “批量添加歌曲、拖拽排序、一键分享到社交平台”,系统自动生成 “歌单封面(基于歌曲风格配色)”。 音乐分类浏览:按 “曲风(流行 / 摇滚 / 古典)、语言(国语 / 英语 / 日语)、年代(80 后经典 / 2023 新歌)” 分层浏览,每个分类页展示 “TOP50 榜单”。 社交互动功能: 动态广场:查看 “关注的用户 / 音乐人发布的动态(如‘分享新歌感受’)、好友正在听的歌曲”,支持 “点赞 / 评论 / 转发”,可直接点击动态中的歌曲播放。 听歌排行:个人页展示 “本周听歌 TOP10、累计听歌时长”,平台定期生成 “全球 / 好友榜”(如 “好友中你本周听歌时长排名第 3”)。 音乐圈:加入 “特定曲风圈子(如‘古典音乐爱好者’)”,参与 “话题讨论(如‘你心中最经典的钢琴曲’)、线上歌单共创”。 (2)音乐人端(创作者中心) 作品管理: 音乐上传:支持 “无损音频(FLAC/WAV)+ 歌词文件(LRC)+ 专辑封面” 上传,填写 “歌曲信息
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值