一 . 高效加载 Bitmap

BitMapFactory 提供了四类方法: decodeFile,decodeResource,decodeStream 和 decodeByteArray 分别用于从文件系统,资源,输入流以及字节数组中加载出一个 Bitmap 对象。
高效加载 Bitmap 很简单,即采用 BitMapFactory.options 来加载所需要尺寸图片。BitMapFactory.options 就可以按照一定的采样率来加载缩小后的图片,将缩小后的图片置于 ImageView 中显示。
通过采样率即可高效的加载图片,遵循如下方式获取采样率:
BitmapFactory.Options 的 inJustDecodeBounds 参数设置为 true 并加载图片BitmapFactory.Options 中取出图片的原始宽高信息,即对应于 outWidth 和 outHeight 参数BitmapFactory.Options 的 injustDecodeBounds 参数设置为 false,然后重新加载图片过上述四个步骤,加载出的图片就是最终缩放后的图片,当然也有可能没有缩放。
代码实现如下:
public Bitmap decodeSampledBitmapFromResource(Resources res, int resId, int reqWidth, int reqHeight) {
// First decode with inJustDecodeBounds=true to check dimensions
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(res, resId, options);
// Calculate inSampleSize
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
// Decode bitmap with inSampleSize set
options.inJustDecodeBounds = false;
return BitmapFactory.decodeResource(res, resId, options);
}
public int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
if (reqWidth == 0 || reqHeight == 0) {
return 1;
}
// Raw height and width of image
final int height = options.outHeight;
final int width = options.outWidth;
Log.d(TAG, "origin, w= " + width + " h=" + height);
int inSampleSize = 1;
if (height > reqHeight || width > reqWidth) {
final int halfHeight = height / 2;
final int halfWidth = width / 2;
// Calculate the largest inSampleSize value that is a power of 2 and
// keeps both height and width larger than the requested height and width.
while ((halfHeight / inSampleSize) >= reqHeight && (halfWidth / inSampleSize) >= reqWidth) {
inSampleSize *= 2;
}
}
Log.d(TAG, "sampleSize:" + inSampleSize);
return inSampleSize;
}
实际使用就可以像下面这样了,如加载 100*100 的图片大小,就可以像下面这样高效的加载图片了:
mImageView.setImageBitmap( decodeSampledBitmapFromResource(getResource(),R.id.myimage,100,100));
二 . Android 中的缓存策略
目前常用的算法是 LRU,即近期最少使用算法,当缓存存满时,会优先淘汰近期最少使用的缓存对象
2.1 LruCache
LruCache 是一个泛型类,其内部实现机制是 LinkedHashMap 以强引用的方式存储外部的缓存对象,提供了 get() 和 put() 来完成缓存对象的存取。当缓存满了,移除较早的缓存对象,再添加新的。LruCache 是线程安全的。
2.2 DiskLriCache
DiskLruCache 用于实现存储设备缓存,即磁盘缓存。
2.2.1 DiskLruCache 的创建
由于它不属于 Android SDK的一部分,所以不能通过构造方法来创建,提供了 open() 方法用于自身的创建
public static DiskLruCache open(File directory,int appversion,int valueCount,long maxSize);
典型的 DiskLruCache 的创建过程
private static final Disk_CACHE_SIZE = 1024*1024*50;//50M
File diskCaCheDir = getDiskCacheDir(mContext,"bitmap");
if(!diskCacheDir.exists()){
diskCacheDir.mkdirs();
}
mDiskLruCache = DiskLruCache.open(diskCaCheDir,1,1,Disk_CACHE_SIZE);
第三个参数表示单个节点所对应的数据,一般设置为1即可。
2.2.2 DiskLruCache 的缓存添加 缓存的添加操作是通过 Editor 完成的, Editor 表示一个缓存对象的编辑对象。DiskLruCache 不允许同时编辑一个缓存对象。
2.2.3 DiskLruCache 的缓存查找
缓存查找过程也需要将 url 转换为 key,通过 DiskLruCache 的 get() 得到一个 Snapshot 对象,然后通过该对象即可得到缓存的文件输入流,得到文件输入流即可得到 Bitmap 对象了。为了避免加载过程中 OOM,一般不会直接加载原始图片。在前面介绍通过 BitmapFactory.Options 来加载一张缩放后的图片,但是那种方法对 FileInputStream 的缩放存在问题,原因是 FileInputStream 是一种有序的文件流,而两次 decodeStream 调用影响了文件流的位置属性,导致了第二次 decodeStream 时得到的是 null。为了解决这个问题,可以通过文件流得到其对应的文件描述符,然后通过 BitmapFactory.decodeFileDescriptor 方法来加载一张缩放过后的图片。
Bitmap bitmap = null;
String key = hashKeyFormUrl(url);
DiskLruCache.Snapshot snapShot = mDiskLruCache.get(key);
if (snapShot != null) {
FileInputStream fileInputStream = (FileInputStream)snapShot.getInputStream(DISK_CACHE_INDEX);
// 获取文件描述符
FileDescriptor fileDescriptor = fileInputStream.getFD();
// 通过 BitmapFactory.decodeFileDescriptor 来加载一张缩放后的图片
bitmap = mImageResizer.decodeSampledBitmapFromFileDescriptor(fileDescriptor,
reqWidth, reqHeight);
if (bitmap != null) {
addBitmapToMemoryCache(key, bitmap);
}
}
return bitmap;
}
三 . ImageLoader 的实现
具备的功能,即图片的同步加载,异步加载,图片的压缩,内存缓存,磁盘缓存以及网络拉取。
3.1 图片压缩功能
如前面所述。
3.2 内存缓存和磁盘缓存的实现
选择 LruCache 和 DiskLruCache 来分别完成内存缓存和磁盘缓存的工作
3.3 同步加载和异步加载的接口设计
关于同步加载:从 loadBitmap 的实现可以看出,其工作过程遵循如下几个步骤:先试着从内存缓存中读取图片,接着从磁盘缓存中读取图片,最后试着从网络拉取图片。另外该方法不能在主线程中调用,否则就会抛出异常。因为加载图片是一个耗时的操作。
关于异步加载:从 bindBitmap 中可以看出,binfBitmap 会先试着从内存缓存中读取结果,如果成功就直接返回,否则会从线程池中去调用 loadBitmap() ,当加载成功后,再讲图片,图片地址以及需要绑定的 ImageView 封装成一个 loaderResult 对象,通过 mMainHandler 向主线程发送一个消息,这样就可以在主线程中给 ImageView 设置图片了。图片的异步加载是一个很有用的功能,很多时候调用者不想在单独的线程中以同步的方式来加载图片,并将图片设置给需要的 ImageVIew, 从而ImageLoader 内部需要自己需要在内部线程中加载图片,并且将图片设置给所需要的 ImageView。
ImageLoader源码可以点击这里:下载 查看ImageLoader的实现
四 . ImageLoader 的使用
核心是 ImageAdapter , 其中的 getView() 的核心方法如下:
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.image_list_item,parent, false);
holder = new ViewHolder();
holder.imageView = (ImageView) convertView.findViewById(R.id.image);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
ImageView imageView = holder.imageView;
final String tag = (String)imageView.getTag();
final String uri = getItem(position);
if (!uri.equals(tag)) {
imageView.setImageDrawable(mDefaultBitmapDrawable);
}
if (mIsGridViewIdle && mCanGetBitmapFromNetWork) {
imageView.setTag(uri);
// 这句话将图片的复杂加载过程交给 ImageLoader 了
mImageLoader.bindBitmap(uri, imageView, mImageWidth, mImageWidth);
}
return convertView;
}
对于上述代码 ImageAdapter 来说, ImageLoader 的加载图片的复杂过程,更不需要知道。
优化列表卡顿现象:
总结
以上就是这篇文章的全部内容了,希望本文的内容对给我Android开发者们能带来一定的帮助,如果有疑问大家可以留言交流。
# bitmap优化
# android
# 加载bitmap
# cache
# Android性能优化之Bitmap图片优化详解
# Android Bitmap详解及Bitmap的内存优化
# 解析Android开发优化之:对Bitmap的内存优化详解
# Android 性能优化系列之bitmap图片优化
# 加载
# 是一个
# 采样率
# 就可以
# 试着
# 设置为
# 可以看出
# 所需要
# 方法来
# 的是
# 近期
# 就会
# 给我
# 也有
# 是一种
# 两次
# 所需
# 能在
# 这句话
# 可以通过
相关文章:
早安海报制作网站推荐大全,企业早安海报怎么每天更换?
如何选择美橙互联多站合一建站方案?
TestNG的testng.xml配置文件怎么写
如何快速生成专业多端适配建站电话?
C++如何编写函数模板?(泛型编程入门)
广州网站建站公司选择指南:建站流程与SEO优化关键词解析
如何选择适合PHP云建站的开源框架?
如何快速登录WAP自助建站平台?
免费视频制作网站,更新又快又好的免费电影网站?
孙琪峥织梦建站教程如何优化数据库安全?
如何快速生成可下载的建站源码工具?
如何通过wdcp面板快速创建网站?
制作ppt免费网站有哪些,有哪些比较好的ppt模板下载网站?
如何批量查询域名的建站时间记录?
杭州银行网站设计制作流程,杭州银行怎么开通认证方式?
长春网站建设制作公司,长春的网络公司怎么样主要是能做网站的?
建站之星展会模板:智能建站与自助搭建高效解决方案
盘锦网站制作公司,盘锦大洼有多少5G网站?
如何用AWS免费套餐快速搭建高效网站?
学校免费自助建站系统:智能生成+拖拽设计+多端适配
建站之星如何通过成品分离优化网站效率?
简单实现Android文件上传
番禺网站制作公司哪家值得合作,番禺图书馆新馆开放了吗?
寿县云建站:智能SEO优化与多行业模板快速上线指南
网站制作的软件有哪些,制作微信公众号除了秀米还有哪些比较好用的平台?
如何通过虚拟主机空间快速建站?
电脑免费海报制作网站推荐,招聘海报哪个网站多?
武清网站制作公司,天津武清个人营业执照注销查询系统网站?
如何彻底删除建站之星生成的Banner?
建站主机系统SEO优化与智能配置核心关键词操作指南
网站制作培训多少钱一个月,网站优化seo培训课程有哪些?
如何配置IIS站点权限与局域网访问?
建站之星如何配置系统实现高效建站?
电商网站制作价格怎么算,网上拍卖流程以及规则?
上海网站制作开发公司,上海买房比较好的网站有哪些?
如何在搬瓦工VPS快速搭建网站?
小自动建站系统:AI智能生成+拖拽模板,多端适配一键搭建
如何实现建站之星域名转发设置?
上海网站制作网站建设公司,建筑电工证网上查询系统入口?
如何使用Golang安装API文档生成工具_快速生成接口文档
视频网站app制作软件,有什么好的视频聊天网站或者软件?
高性价比服务器租赁——企业级配置与24小时运维服务
如何快速完成中国万网建站详细流程?
小说建站VPS选用指南:性能对比、配置优化与建站方案解析
网页制作模板网站推荐,网页设计海报之类的素材哪里好?
香港服务器建站指南:免备案优势与SEO优化技巧全解析
,石家庄四十八中学官网?
北京营销型网站制作公司,可以用python做一个营销推广网站吗?
制作网站的软件免费下载,免费制作app哪个平台好?
电商网站制作多少钱一个,电子商务公司的网站制作费用计入什么科目?
*请认真填写需求信息,我们会在24小时内与您取得联系。