Bitmap的加载和Cache
2016-06-12 16:58
204 查看
一、Bitmap的高效加载
1、Bitmap的加载方式
1)、decodeFile
2)、decodeResource
3)、decodeStream
4)、decodeByteArray
2、BitmapFactory.Options缩放图片:采样率inSampleSize
1)、采样率取值:取值为2的指数,如果不是,则自动向下取整选择最接近的2的指数代替。
2)、采样率选择:缩放后的大小应大于ImageView大小,否则会由于拉伸导致模糊
3)、加载图片:
a、BitmapFactory.Options的inJustDecodeBounds设置为true并加载图片
b、从BitmapFactory.Options的outWidth和outHeight参数取出图片原始宽高
c、计算采样率
d、BitmapFactory.Options的inJustDecodeBounds设置为false并重新加载图片
二、Android中的缓存策略
1、缓存:
1)、概念:程序第一次从网络加载图片后,将其缓存到存储设备上,下次使用就不再从网络上获取了。为提高用户体验,还会在内存中缓存一份,这样请求图片时,首先去内存获取,没有则从存储设备获取,再没有则从网络加载。
2)、缓存策略:缓存的添加、获取和删除。常用算法:LRU
3)、LruCache
a、创建
b、获取、添加、删除一个缓存对象
4)、DiskLruCache
a、创建
<span style="white-space:pre"> </span>File diskCacheDir = getDiskCacheDir(mContext, "bitmap");//获取缓存文件夹的方法
if (!diskCacheDir.exists()) {
diskCacheDir.mkdirs();
}
if (getUsableSpace(diskCacheDir) > DISK_CACHE_SIZE) {
try {
mDiskLruCache = DiskLruCache.open(diskCacheDir, 1, 1,
DISK_CACHE_SIZE);
mIsDiskLruCacheCreated = true;
} catch (IOException e) {
e.printStackTrace();
}
}b、添加
// 使用MD5算法获取字符串的Hash值//
private String hashKeyFormUrl(String url) {
String cacheKey;
try {
final MessageDigest mDigest = MessageDigest.getInstance("MD5");
mDigest.update(url.getBytes());
cacheKey = bytesToHexString(mDigest.digest());
} catch (NoSuchAlgorithmException e) {
cacheKey = String.valueOf(url.hashCode());
}
return cacheKey;
}
//将MD5字节数组转换成字符串
private String bytesToHexString(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < bytes.length; i++) {
String hex = Integer.toHexString(0xFF & bytes[i]);
if (hex.length() == 1) {
sb.append('0');
}
sb.append(hex);
}
return sb.toString();
}
<span style="white-space:pre"> </span>//查找缓存
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();
bitmap = mImageResizer.decodeSampledBitmapFromFileDescriptor(
fileDescriptor, reqWidth, reqHeight);
if (bitmap != null) {
addBitmapToMemoryCache(key, bitmap);
}
}2、ImageLoader
1)、图片压缩
2)、内存缓存和磁盘缓存
3)、同步加载和异步加载接口的设计
a、加载顺序:内存、磁盘、网络
b、检查线程是否为主线程:加载网络缓存时调用
c、使用线程池和Handler提供并发和访问UI的能力
3、使用ImageLoader
1)照片墙
2)列表卡顿的优化
a、异步加载耗时任务
b、控制异步任务执行频率:列表滑动时不加载图片
c、为Activity开启硬件加速: <span style="white-space:pre"> </span>android:hardwareAccelerated="true"
1、Bitmap的加载方式
1)、decodeFile
2)、decodeResource
3)、decodeStream
4)、decodeByteArray
2、BitmapFactory.Options缩放图片:采样率inSampleSize
1)、采样率取值:取值为2的指数,如果不是,则自动向下取整选择最接近的2的指数代替。
2)、采样率选择:缩放后的大小应大于ImageView大小,否则会由于拉伸导致模糊
3)、加载图片:
a、BitmapFactory.Options的inJustDecodeBounds设置为true并加载图片
b、从BitmapFactory.Options的outWidth和outHeight参数取出图片原始宽高
c、计算采样率
d、BitmapFactory.Options的inJustDecodeBounds设置为false并重新加载图片
二、Android中的缓存策略
1、缓存:
1)、概念:程序第一次从网络加载图片后,将其缓存到存储设备上,下次使用就不再从网络上获取了。为提高用户体验,还会在内存中缓存一份,这样请求图片时,首先去内存获取,没有则从存储设备获取,再没有则从网络加载。
2)、缓存策略:缓存的添加、获取和删除。常用算法:LRU
3)、LruCache
a、创建
<span style="white-space:pre"> </span>int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024); int cacheSize = maxMemory / 8; mMemoryCache = new LruCache<String, Bitmap>(cacheSize) { @Override protected int sizeOf(String key, Bitmap bitmap) { // TODO Auto-generated method stub return bitmap.getRowBytes() * bitmap.getHeight() / 1024; } };
b、获取、添加、删除一个缓存对象
<span style="white-space:pre"> </span>mMemoryCache.get(key); mMemoryCache.put(key, value); mMemoryCache.remove(key);
4)、DiskLruCache
a、创建
<span style="white-space:pre"> </span>File diskCacheDir = getDiskCacheDir(mContext, "bitmap");//获取缓存文件夹的方法
if (!diskCacheDir.exists()) {
diskCacheDir.mkdirs();
}
if (getUsableSpace(diskCacheDir) > DISK_CACHE_SIZE) {
try {
mDiskLruCache = DiskLruCache.open(diskCacheDir, 1, 1,
DISK_CACHE_SIZE);
mIsDiskLruCacheCreated = true;
} catch (IOException e) {
e.printStackTrace();
}
}b、添加
// 使用MD5算法获取字符串的Hash值//
private String hashKeyFormUrl(String url) {
String cacheKey;
try {
final MessageDigest mDigest = MessageDigest.getInstance("MD5");
mDigest.update(url.getBytes());
cacheKey = bytesToHexString(mDigest.digest());
} catch (NoSuchAlgorithmException e) {
cacheKey = String.valueOf(url.hashCode());
}
return cacheKey;
}
//将MD5字节数组转换成字符串
private String bytesToHexString(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < bytes.length; i++) {
String hex = Integer.toHexString(0xFF & bytes[i]);
if (hex.length() == 1) {
sb.append('0');
}
sb.append(hex);
}
return sb.toString();
}
<span style="white-space:pre"> </span>//获取editor创建输出流,通过输出流将文件写入文件系统 String key = hashKeyFormUrl(url); DiskLruCache.Editor editor = mDiskLruCache.edit(key); if (editor != null) { OutputStream outputStream = editor .newOutputStream(DISK_CACHE_INDEX); if (downloadUrlToStream(url, outputStream)) { editor.commit(); } else { editor.abort(); } mDiskLruCache.flush(); } /** * 将文件输出流写入文件系统 * * @param urlString * 图片地址 * @param outputStream * 输出流 * @return 写入结果状态 */ public boolean downloadUrlToStream(String urlString, OutputStream outputStream) { HttpURLConnection urlConnection = null; BufferedOutputStream out = null; BufferedInputStream in = null; try { final URL url = new URL(urlString); urlConnection = (HttpURLConnection) url.openConnection(); in = new BufferedInputStream(urlConnection.getInputStream(), IO_BUFFER_SIZE); out = new BufferedOutputStream(outputStream, IO_BUFFER_SIZE); int b; while ((b = in.read()) != -1) { out.write(b); } return true; } catch (IOException e) { Log.e(TAG, "downloadBitmap failed." + e); } finally { if (urlConnection != null) { urlConnection.disconnect(); } MyUtils.close(out);//关闭流的方法 MyUtils.close(in); } return false; }c、查找
<span style="white-space:pre"> </span>//查找缓存
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();
bitmap = mImageResizer.decodeSampledBitmapFromFileDescriptor(
fileDescriptor, reqWidth, reqHeight);
if (bitmap != null) {
addBitmapToMemoryCache(key, bitmap);
}
}2、ImageLoader
1)、图片压缩
2)、内存缓存和磁盘缓存
3)、同步加载和异步加载接口的设计
a、加载顺序:内存、磁盘、网络
b、检查线程是否为主线程:加载网络缓存时调用
c、使用线程池和Handler提供并发和访问UI的能力
3、使用ImageLoader
1)照片墙
2)列表卡顿的优化
a、异步加载耗时任务
b、控制异步任务执行频率:列表滑动时不加载图片
c、为Activity开启硬件加速: <span style="white-space:pre"> </span>android:hardwareAccelerated="true"
相关文章推荐
- 学习Tensorflow,反卷积
- ActiveMQ消息发送和接收
- PHP设计模式之装饰器模式
- Ceph的基本安装
- 网站优化技术概述
- 获取easyui-combobox value值
- HTML常用代码的搜集
- 题目1105:字符串的反码
- 学习Tensorflow,反卷积
- H5+App开发框架汇总
- 《深入理解Java虚拟机》Java内存区域与内存溢出异常
- 如何做决策
- 【小明有啥说啥】我不会写标题,端午随便分享几点小技巧
- mac 下终端访问文件出现“Permission Denied”解决方案
- Hbase API中常用类介绍和使用
- Win2008 R2 WEB 服务器安全设置指南之文件夹权限设置技巧
- spring boot使用mongo:code1
- windows搭建python环境之MySQLdb
- 用两个栈实现队列
- Session的应用