Bitmap的加载和Cache

Bitmap的加载和Cache

读[Android开发艺术探索]笔记之二

Bitmap的高效加载

bitmap就是android中的图片,在BitmapFactory提供了四类方法
- decodeFile 文件系统加载(内部间接调用decodeStream)
- decodeResource 从资源中加载(内部间接调用decodeStream)
- decodeStream 从输入流中加载
- decodeByteArray 从字节数组中加载

高效加载图片,一般会缩小图片尺寸
1. BitmapFactory.Options的injustDecodeBounds参数设置为true加载图片
- 当它设置为true的时候, BitmapFactory只会去解析图片的宽高,不会真正的加载图片.它是一个轻量级的操作.

```
    options.inJustDecodeBounds=true;
BitmapFactory.decodeResource(res,id,options);
```
  1. 从BitmapFactory.Options中取出图片的原始宽高,outWidth和outHeight

    • 它拿到的宽高和具体设备的屏幕密度有关,所以可能在不同的设备上值不一样
    int outHeight = options.outHeight;
    int outWidth = options.outWidth;
  2. 根据采样率和实际需求,计算出inSampleSize

    options.inSampleSize=3;//设置需要的采样率
  3. 然后再将BitmapFactory.Optins的injustDecodeBounds参数设置为false,重新加载图片

    options.inJustDecodeBounds=false;
    Bitmap bitmap = BitmapFactory.decodeResource(res, id, options);
    
BitmapFactory的四种方法多可以这样采样加载(decodeStream使用有点特殊)

Android 中的缓存策略

为什么需要缓存
  • 节省流量 (缓存到内存或者SD卡,就不需要在网上反复下载)
  • 提高效率 (内存>SD卡>网络)
缓存算法LRU 近期最少使用算法
  • 当缓存空间不足是,优先释放最近使用较少的数据
  • LruCahce 内存Lru缓存
  • DiskLruCache 磁盘Lru缓存
LruCache
  • LruCache 是Android3.1提供的类.低版本可以使用support-v4兼容包
  • LruCache 是一个泛型类 内部包装了一个LinkedHashMap(强引用).提供set/put方法来获取和添加缓存对象.
  • 早期处理缓存方式是使用软引用和弱引用的方式实现,但是在Android2.1之后,这两个引用不在可靠
private Map<String, SoftReference<Bitmap>> map = new HashMap<>();

//早期缓存处理
public void setMemoryCache(String url, Bitmap bitmap) {
    SoftReference<Bitmap> soft = new SoftReference<Bitmap>(bitmap);//用软引用包装bitmap
    map.put(url, soft);
}

public Bitmap getMemoryCache(String url) {
    SoftReference<Bitmap> soft = map.get(url);
    if (soft != null) {
        Bitmap bitmap = soft.get();//从软引用中取出当前对象
        return bitmap;
    }
    return
- 强引用 直接的对象引用 
- 软引用 SoftReference 内存不足时,会被回收
- 弱引用 WeakReference 随时可能被回收
- 虚引用 PhantomReference 基本一创建就被回收

- 使用方法
1. 获得当前机型给每个APP分配的最大内存

```
//当前机型给每个APP分配的最大内存
long maxMemory = Runtime.getRuntime().maxMemory();
```

2. 创建LruCache 并设置它的最大内存

```
//一般我们给lruCache分配内存为最大内存的1/8
long lruCacheMaxMemory = maxMemory / 8;
//创建lruCache 传入设置的最多内存
LruCache lruCache = new LruCache((int) lruCacheMaxMemory);
```
3. 重新sizeOf方法 返回当前需要缓存图片的大小

```
    LruCache lruCache = new LruCache((int) lruCacheMaxMemory){
        @Override
        protected int sizeOf(Object key, Object value) {


            int bitmapSize = bitmap.getRowBytes() * bitmap.getHeight();

            return bitmapSize;
        }
    };
```
4. 通过get / put 方法来获取/添加缓存

```
lruCache.get(key);

lruCache.put(key,bitmap);
```
5. 通过remove方法 删除一个缓存对象

```
lruCache.remove(key);
```
DiskLruCache
用于实现存储设备缓存,即磁盘缓存.非Google官方编写,但获得官方认证.
获取
由于DiskLruCache并不是由Google官方编写的,所以这个类并没有被包含在Android
API当中,我们需要将这个类从网上下载下来,然后手动添加到项目当中。
DiskLruCache的源码在Google Source上,
地址如下:
android.googlesource.com/platform/libcore/+/jb-mr2-release/luni/src/main/java/libcore/io/DiskLruCache.java
使用方法
  1. DiskLruCache的创建
public static DiskLruCache open(File directory, int appVersion, int 
valueCount, long maxSize)  
四个参数
- 缓存存放的路径
- 版本号 默认为1.效果是当版本号发生改变的时候清空缓存文件.开发实际意义不大
- 代表单个节点对应数据的个数 一般为1
- 表示缓存总大小
  1. DiskLruCache的缓存添加

    缓存的添加是通过Editor完成

    public Editor edit(String key) throws IOException  

    Editor表示缓存对象的编辑器,我们看到这里需要传入一个key,这个key一般使用图片的MD5来做为它的值.

    获得编辑器editor之后,在调用它的newOutputStream方法,这里的传入一个常量0(因为我们设置了一个节点只有一个数据),得到输出流.

    OutputStream outputStream = editor.newOutputStream(0); 

    有了文件输出流就可以调用downloadUrlToStream方法了 把图片url和输出流传入

    downloadUrlToStream(imageUrl, outputStream)

    当它返回true 成功时 再使用editor调用commit 提交 才是真正传输了

    editor.commit()
  2. DiskLruCache的缓存查找

    方法同添加 同样需要图片url的md5 做为key.在get出Snapshot对象,然后再用对象拿到输入流,有流就有文件了

    通过key拿到Snapshot对象

public synchronized Snapshot get(String key) throws IOException  
再用对象拿到输出流
InputStream is = snapShot.getInputStream(0);
最后常规操作,用流得到文件
Bitmap bitmap = BitmapFactory.decodeStream(is);  
mImage.setImageBitmap(bitmap);

图片的三级缓存

  • 内存缓存:速度很快,不浪费流量,不联网
  • 本地缓存:速度快,不浪费流量
  • 网络缓存:速度慢,浪费流量

    先从内存缓存去获取图片,如果有直接返回,如果没有继续从SD卡中获取;SD卡中有数据直接返回,如果没有再联网获取。其实现过程就利用到LruCache和DiskLruCache来实现的

实际开始三级缓存基本都使用第三方,查看原码即可.在
http://blog.csdn.net/guolin_blog/article/details/28863651(参考)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值