原文地址

http://blog.csdn.net/ceko_wu/article/details/45244259



1、图片缓存管理的必要性

        Android应用为什么要做一些图片缓存的管理?

       1)内存管理必要性

      android每个进程的虚拟机对内存的管理与其他的一些系统不太一样,比如iOS,ios对于内存这块的管理,开发者可以自己手动去释放,但在android中没有提供给开发人员释放内存的功能,android虚拟机只有在内存达到限制   的值时才会主动去回收,应用调用System.gc也不能解决内存问题,gc()函数的作用只是提醒虚拟机:程序员希望进行一次垃圾回收。但是它不能保证垃圾回收一定会进行,而且具体什么时候进行是取决于具体的虚拟机  的,不同的虚拟机有不同的对策。

       应用中我们有大量的图片操作,比如像论坛类型的应用,我们加载过的图片肯定希望下次加载的时候能够更快的使用,如果可以放在内存中,无疑将会是最快的,但内存是有限的,每个进程最大的内存是有限制的,且又因为它的回收机制,所以我们必须要做内存管理,否则会出现oom。

    2)磁盘管理的重要性

        内存是有限的,不可能所有的图片都放在内存中,但需要提升加载速度,节约流量,下载过的图片希望下次继续使用,只能存放在本地磁盘中,android中的磁盘与pc机不太一样,三方应用可以使用的磁盘一个是应用安装目录/data/data/包名,另外就是sdcard目录,但虽然是本地缓存我们也不能缓存过多的文件,如果缓存过多会占用太多的空间。

2、LRU 内存管理实现方案


  • java.util.LinkedHashMap
    java提供了LinkedHashMap,它是HashMap的一种,它有一个重要的功能可以设置存放的元素最大的个数,当map中的元素超过设置的值时,它可以移除最老的值。
    它实现了lru的算法。

  • 实现原理
    根据LinkedHashMap的功能,我们将图片的bitmap存到LinkedHashMap中,且设置存储最大的值,根据其原理,如果超过其容量就会自动移除最老的值。

public class LRULinkedHashMap extends java.util.LinkedHashMap { /** serialVersionUID */  private static final long serialVersionUID = -5933045562735378538L;  /** 最大数据存储容量 */  private static final int  LRU_MAX_CAPACITY     = 1024;  /** 存储数据容量  */  private int               capacity;  /**  * 默认构造方法  */  public LRULinkedHashMap() {      super();  }  /**  * 带参数构造方法  * @param initialCapacity   容量  * @param loadFactor        装载因子  * @param isLRU             是否使用lru算法,true:使用(按方案顺序排序);false:不使用(按存储顺序排序)  */  public LRULinkedHashMap(int initialCapacity, float loadFactor, boolean isLRU) {      super(initialCapacity, loadFactor, true);      capacity = LRU_MAX_CAPACITY;  }  /**  * 带参数构造方法  * @param initialCapacity   容量  * @param loadFactor        装载因子  * @param isLRU             是否使用lru算法,true:使用(按方案顺序排序);false:不使用(按存储顺序排序)  * @param lruCapacity       lru存储数据容量         */  public LRULinkedHashMap(int initialCapacity, float loadFactor, boolean isLRU, int lruCapacity) {      super(initialCapacity, loadFactor, true);      this.capacity = lruCapacity;  }  /**   * @see java.util.LinkedHashMap#removeEldestEntry(java.util.Map.Entry)  */  @Override  protected boolean removeEldestEntry(Entry eldest) {            if(size() > capacity) {          return true;      }      return false;  }  }

下载好的图片直接通过put(url,bitmap)存储起来,需要的使用的时候通过get(url)判断是否有存储在内存中,如果存储则直接使用bitmap,当然bitmap最好使用弱引用

3、磁盘LRU 管理实现方案

    磁盘管理采用google开源jar包 disklrucache-2.0.1.jar,该jar实现了对本地文件的管理。

    1)初始化

 public DiskLruImageCache(Context context,String uniqueName, int diskCacheSize,        CompressFormat compressFormat, int quality ) {        try {                final File diskCacheDir = getCacheDir(context, uniqueName );                mDiskCache = DiskLruCache.open( diskCacheDir, APP_VERSION, VALUE_COUNT, diskCacheSize );                mCompressFormat = compressFormat;                mCompressQuality = quality;            } catch (IOException e) {                e.printStackTrace();            }    }

需要设置保存的路径以及压缩方式,以及最大存储大小。

2)存储

    public void putBitmap( String key, Bitmap data ) {        UtilLog.d("putBitmap key==="+key);        DiskLruCache.Editor editor = null;        try {            editor = mDiskCache.edit( key );            if ( editor == null ) {                return;            }            OutputStream out = null;            boolean result=false;            try {                out = editor.newOutputStream( 0 );                result= data.compress( mCompressFormat, mCompressQuality, out );                editor.commit();                mDiskCache.flush();            } finally {                if ( out != null ) {                    out.close();                }            }        } catch (IOException e) {        e.printStackTrace();            try {                if ( editor != null ) {                    editor.abort();                }            } catch (IOException ignored) {            ignored.printStackTrace();            }                   }    }

根据图片的url作为查询的key值进行存储

3)获取存储的图片

 public Bitmap getBitmap( String key ) {        Bitmap bitmap = null;        DiskLruCache.Snapshot snapshot = null;        try {            snapshot = mDiskCache.get( key );if (snapshot != null) {InputStream inputStream = snapshot.getInputStream(0);if (inputStream != null) {bitmap = BitmapFactory.decodeStream(inputStream);inputStream.close();}}        } catch ( IOException e ) {            e.printStackTrace();        } finally {            if ( snapshot != null ) {                snapshot.close();            }        }        return bitmap;    }

获取时根据图片的url获取图片的bitmap

4、图片缓存管理方案总结

        在实际应用中,由于内存的读取速度比磁盘的读取速度快很多,所以优先使用内存,如果内存中没有的情况下再从磁盘查找,如果磁盘查找没有的情况下再从网络下载。

当然现在图片的缓存这块也可以不用自己手动处理,有很多的三方jar包已经实现了这些功能,使用也比较方便。Android-Universal-Image-Loader实现上述的管理。


更多相关文章

  1. Android(安卓)匿名共享内存C接口分析
  2. 【Android】安卓常见的内存泄漏:OOM,bitmap
  3. MacBook下配置android adb命令使用环境
  4. Android将胜过Windows Mobile五大原因
  5. Android大图片内存清理
  6. Android上鲜为人知的UI控件介绍和使用
  7. 箭头函数的基础使用
  8. NPM 和webpack 的基础使用
  9. Python list sort方法的具体使用

随机推荐

  1. fir.im Weekly - iOS / Android(安卓)动
  2. Android 的cpu 硬盘 内存 网络设置 系统
  3. How to discover memory usage of my app
  4. android calendar的使用
  5. 史上最易懂的Android(安卓)jni开发资料--
  6. android一对多通信
  7. [Android(安卓)UI] shape和selector的结
  8. Android启动时启动Activity 的定义的位置
  9. android ScreenObserver 实现打开锁屏键
  10. Android之实现手机号码拦截