一起动手编写Android图片加载框架

2019-12-10 18:16:05王冬梅

在以上代码中,我们创建了一个LruCache实例,并指定它的maxSize为当前进程可用内存的1/8。我们使用String作为key,value自然是Bitmap。第6行到第8行我们重写了sizeOf方法,这个方法被LruCache用来计算一个缓存对象的大小。我们使用了getByteCount方法返回Bitmap对象以字节为单位的方法,又除以了1024,转换为KB为单位的大小,以达到与cacheSize的单位统一。

(2)获取缓存对象
   LruCache类通过get方法来获取缓存对象,get方法的源码如下:

 

public final V get(K key) {
    if (key == null) {
      throw new NullPointerException("key == null");
    }

    V mapValue;
    synchronized (this) {
      mapValue = map.get(key);
      if (mapValue != null) {
        hitCount++;
        return mapValue;
      }
      missCount++;
    }

    /*
     * Attempt to create a value. This may take a long time, and the map
     * may be different when create() returns. If a conflicting value was
     * added to the map while create() was working, we leave that value in
     * the map and release the created value.
     */

    V createdValue = create(key);
    if (createdValue == null) {
      return null;
    }

    synchronized (this) {
      createCount++;
      mapValue = map.put(key, createdValue);

      if (mapValue != null) {
        // There was a conflict so undo that last put
        map.put(key, mapValue);
      } else {
        size += safeSizeOf(key, createdValue);
      }
    }

    if (mapValue != null) {
      entryRemoved(false, key, createdValue, mapValue);
      return mapValue;
    } else {
      trimToSize(maxSize);
      return createdValue;
    }
  }

    通过以上代码我们了解到,首先会尝试根据key获取相应value(第8行),若不存在则会新建一个key-value对,并将它放入到LinkedHashMap中。从get方法的实现我们可以看到,它用synchronized关键字作了同步,因此这个方法是线程安全的。实际上,LruCache类对所有可能涉及并发数据访问的方法都作了同步。

(3)添加缓存对象
    在添加缓存对象之前,我们先得确定用什么作为被缓存的Bitmap对象的key,一种很直接的做法便是使用Bitmap的URL作为key,然而由于URL中存在一些特殊字符,所以可能会产生一些问题。基于以上原因,我们可以考虑使用URL的md5值作为key,这能够很好的保证不同的url具有不同的key,而且相同的url得到的key相同。我们自定义一个getKeyFromUrl方法来通过URI获取key,该方法的代码如下: