一,Bitmap的高效加载
-
如何加载一个图片?
BitmapFactiory提供了四个方法:
decodeFile:从文件系统加载Bitmap对象
decodeResource:从资源中加载
decodeStream:通过输入流加载
decodeByteArray:通过字节数组加载
其中decodeFile与decodeResource又间接调用了decodeStream -
如何高效的加载Bitmap思路?
采用BitmapFactory.Options 来加载所需尺寸的图片,因为有的时候我们控件所显示的图片尺寸没有图片那么大,所以可以将其缩小,按照一定的采样率来加载图片从而降低内存的占用避免OOM。
通过BitmapFactory.Options来进行缩放图片,主要用到inSampleSize参数,当inSampleSize为1时,采用后的图片大小为原始大小,当inSampleSize大于时 比如为2时则采用后的图片宽高均为原来的1/2,像素为原来的1/4,占有的内存大小也为原来的1/4 -
如何获取采样率
(1)将BitmapFactory.Options的inJustDecodeBounds的参数设为true并加载图片
(2)从itmapFactory.Options中取出图片的原始宽高信息
(3)根据采样率的规则,以及目标view展示的大小,计算出采样率inSampleSize
(4)将itmapFactory.Options的inJustDecodeBounds参数设为false,重新加载图片
注:inJustDecodeBounds设为true只会解析图片的宽高信息,不会真的加载图片。
public static Bitmap decodeSampledBitmapFromResource(Resources resources, int resId,
int reqWidth, int reqHeight) {
final BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeResource(resources, resId, options);
options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
options.inJustDecodeBounds=false;
return BitmapFactory.decodeResource(resources, resId, options);
}
public static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
int inSampleSize = 1;
final int width = options.outWidth;
final int height = options.outHeight;
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;
}
mImageView,setImageBitmap(decodeSampledBitmapFromResource(getResources(),R.id.imageview,100,100))
二,Android中的缓存策略
-
LRUCache(线程安全)
LRU算法:近期最少使用算法
是一个泛型类,内部采用一个LinkedHashMap以强引用的方式存储外界的缓存对象,提供了get,put的方法来完成缓存的获取和添加,当缓存满的时会将较早使用的缓存对象进行移除,再添加新的缓存对象。
强引用:直接对象的引用
软引用:当对象只有软引用存在的时候,系统内存不足时,此对象会随时被gc回收
弱引用:当对象只有弱引用存在时,随时都有可能被GC回收
LruCache的实现
int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
int cacheSize = maxMemory / 8;
LruCache<String, Bitmap> lruCache = new LruCache<String, Bitmap>(cacheSize) {
@Override
protected int sizeOf(String key, Bitmap value) {
return value.getRowBytes()*value.getHeight()/1024;
}
};
设置缓存以及获取缓存
获取缓存
mMemoryCache.get(key);
设置缓存
mMemoryCache.put(key,bitmap);
删除缓存
mMemoryCache.remove(key);
-
DiskLruCache
用于实现存储设备的缓存,即磁盘缓存。通过将缓存对象写入文件系统从而实现缓存效果。
DiskLruCache的创建
public static DiskLruCache open(File directory,int appVersion,int valueCount,long maxSize);
第一个参数:表示磁盘缓存的文件系统中的路径(可以在SD卡上的缓存目录,也可以选择其他位置)
第二个参数:表示应用版本号设置为1即可
第三个参数:设置为1即可
第四个参数:缓存最大值,当超过这个值,DIskLruCache会清除一些缓存
long DISK_CACHE_SIZE=1024*1024*50;
File diskCacheDir=this.getCacheDir();
if(!diskCacheDir.exists()){
diskCacheDir.mkdir();
}
mDiskLruCache=DIsLruCache.open(diskCacheDir,1,1,DISK_CACHE_SIZE);
DiskLruCache的缓存添加
通过Editor完成的,Editor表示一个缓存对象的编辑对象,首先需要获取图片url所对应的key,然后通过key就可以通过edit()来获取到Editor对象,如果这个缓存正在编辑则edit()会返回空,即不允许同事彼岸奇偶及一个缓存对象,一般采用url的md5值来表示key。
通过Editor可以获取到一个文件输出流再将其写入到文件系统上。
通过editor.commit()来进行提交,如果发生异常则调用abort()来回退整个操作。
DiskLruCache的缓存查找
查找过程也是需要将url转化为key值通过DiskLruCache的get方法获取到Snapshot对象,通过它可以得到缓存图片的文件输出流 有了它就可以获取到bitmap对象了











网友评论