Bitmap加载与Cache

一,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 lruCache = new LruCache(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对象了

你可能感兴趣的:(Bitmap加载与Cache)