本文主要介绍一个支持图片自动预取、支持多种缓存算法的图片缓存的使用及功能。图片较大需要SD卡保存情况推荐使用。
与Android LruCache相比主要特性:(1). 使用简单 (2). 轻松获取及预取新图片 (3). 可选择多种缓存算法(FIFO、LIFO、LRU、MRU、LFU、MFU等13种)或自定义缓存算法 (4). 省流量性能佳(有且仅有一个线程获取图片) (5). 支持不同类型网络处理 (6). 可根据系统配置初始化缓存 (7). 扩展性强 (8). 支持队列 (9). 包含map的大多数接口。
适用:获取图片较多且图片不大的应用,如新浪微博、twitter、微信头像、美丽说、蘑菇街、花瓣、淘宝等等。
本文以用ImageCache实现瀑布流为例,示例APK地址见,示例代码地址见,效果图如下:
1、使用
(1)引入公共库
引入(欢迎star和fork^_^)或作为你项目的library,或是自己抽取其中的或部分使用。
(2)调用
仅需简单两步:定义缓存和回调接口、调用get(String imageUrl, View view)异步加载图片。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | /** icon cache **/ public static final ImageCache ICON_CACHE = new ImageCache(); static { OnImageCallbackListener imageCallBack = new OnImageCallbackListener() { private static final long serialVersionUID = 1L; // callback function after image get success, run on ui thread @Override public void onImageLoaded(String imageUrl, Drawable imageDrawable, View view, boolean isInCache){ // can be another view child, like textView and so on if (view != null && imageDrawable != null) { ImageView imageView = (ImageView)view; imageView.setImageDrawable(imageDrawable); } } }; ICON_CACHE.setOnImageCallbackListener(imageCallBack); } |
需要加载图片的地方调用
1 | ICON_CACHE.get(imageUrl, imageView); |
上面代码中new ImageCache()用来定义图片缓存,默认会根据系统内存设置缓存大小。默认缓存算法为LFU(Least Frequently Used),最近最少使用先删除。
setOnImageCallbackListener(imageCallBack);设置图片获取成功回调接口。onImageLoaded(String imageUrl, Drawable imageDrawable, View view, boolean isInCache)的四个参数分别表示图片url,获取到的Drawable,需要使用图片的view(get中传入的view),图片是否已经在缓存中。
get(imageUrl, imageView)异步获取图片,在图片获取成功后会自动调用onImageLoaded将参数传入。
get(String imageUrl,List<String> urlList, View view)异步获取图片,并且会自动预取urlList中的图片。
上面是最简单的实现。
第2部分会介绍支持的其他功能,包括网络类型设置、预取个数设置、多种缓存算法、等待队列开关、图片源读取方式设置、缓存有效时间、命中率及大部分map接口。第3部分介绍listView重叠问题解决、图片oom问题解决。
2、功能介绍(1) 多种构造函数,可根据系统配置初始化缓存
public ImageCache()
public ImageCache(int maxSize)public ImageCache(int maxSize, int threadPoolSize)支持三种构造函数,支持缓存大小和获取图片线程池大小的设置。默认会根据系统可用内存大小设置缓存大小,根据系统Cpu个数设置线程池大小。
(2)、获取图片及自动预取get(String imageUrl, View view)异步获取图片,在图片获取成功后自动调用OnImageCallbackListener的onImageLoaded函数,返回是否已在缓存中
get(String imageUrl, List<String> urlList, View view)异步获取图片,在图片获取成功后自动调用OnImageCallbackListener的onImageLoaded函数,并且根据imageUrl在urlList中的位置向前向后预取图片,返回是否已在缓存中。
public void setForwardCacheNumber(int forwardCacheNumber) 向前预取图片个数设置,默认为PreloadDataCache#DEFAULT_FORWARD_CACHE_NUMBER
public void setBackwardCacheNumber(int backwardCacheNumber)向后预取图片个数设置默认,默认为PreloadDataCache#DEFAULT_BACKWARD_CACHE_NUMBER
public CacheObject<V> get(K key)
public CacheObject<V> get(K key, List<K> keyList)两个接口是直接同步获取图片,且获取成功后不会调用OnImageCallbackListener的onImageLoaded函数
(3)、设置缓存算法setCacheFullRemoveType(CacheFullRemoveType<Drawable> cacheFullRemoveType)
设置缓存算法,缓存算法即为缓存满时为了插入新数据,删除旧数据的规则。
目前包括FIFO、LIFO、LRU、MRU、LFU、MFU、优先级低先删除、优先级高先删除、数据小先删除、数据大先删除、图片小先删除、图片大先删除、永不删除。还可以通过实现CacheFullRemoveType来自定义缓存算法。。默认为RemoveTypeUsedCountSmall,即LRU使用频率低先删除。下面详细介绍各个算法:
RemoveTypeEnterTimeFirst FIFO先进先出,先进入先删除
RemoveTypeEnterTimeLast LIFO后进先出,后进入先删除RemoveTypeLastUsedTimeFirst LRU(Least Recently User),最先使用先删除RemoveTypeLastUsedTimeLast MRU(Most Recently Used),最近使用先删除RemoveTypeUsedCountSmall LFU(Least Frequently Used),使用频率低先删除RemoveTypeUsedCountBig MRU(Most Frequently Used),使用频率高先删除RemoveTypePriorityLow 优先级低先删除RemoveTypePriorityHigh 优先级低先删除RemoveTypeDrawableSmall 图片小的先删除RemoveTypeDrawableLarge 图片大的先删除RemoveTypeDataBig 数据大先删除,根据缓存数据的compareTo函数决定
RemoveTypeDataSmall 数据小先删除,根据缓存数据的compareTo函数决定RemoveTypeNotRemove 不删除,缓存满时不再允许插入新数据
自定义缓存算法只需要实现CacheFullRemoveType的compare方法即可。比较结果小于0表示会被先删除
1 2 3 4 5 6 7 8 9 | public class RemoveTypePriorityHigh<T> implements CacheFullRemoveType<T> { private static final long serialVersionUID = 1L; @Override public int compare(CacheObject<T> obj1, CacheObject<T> obj2) { return (obj2.getPriority() > obj1.getPriority()) ? 1 : ((obj2.getPriority() == obj1.getPriority()) ? 0 : -1); } } |
(4)、是否启用队列setOpenWaitingQueue(boolean isOpenWaitingQueue)
当不同view通过get函数获取图片时,是否开启等待队列。若开启,保存所有view,图片获取成功后依次调用OnImageCallbackListener的onImageLoaded函数;否则仅保存最后调用get的view,图片获取成功后调用OnImageCallbackListener的onImageLoaded函数
默认开启队列等待。如果希望最优性能且场景满足,可设置为false。
(5)、设置图片获取方式接口setOnGetDataListener(OnGetDataListener<String, Drawable> onGetDataListener)
设置图片获取的方式。缓存通过该接口获取图片及预取图片。默认为ImageCache中getDefaultOnGetImageListener,通过url获取图片。你可以重写该方法将图片缓存改为本地图片文件缓存等等。
(6)、优化图片读取a. 设置图片读取http超时
public void setHttpReadTimeOut(int readTimeOutMillis)若readTimeOutMillis小于0表示不设置超时,默认不设置,单位为毫秒b. 设置无网络不读取
public void setContext(Context context)设置context,网络连接失败不会新建线程请求图片。c. 支持不同网络类型的处理
public void setAllowedNetworkTypes(int allowedNetworkTypes)设置允许的网络类型,可选择PreloadDataCache#NETWORK_MOBILE、PreloadDataCache#NETWORK_WIFI或两者都允许。默认两者都允许。注意:这个接口生效必须先setContext(Context context)
(7)、缓存元素有效时间setValidTime(long validTime)
设置缓存元素有效时间,小于0表示不会失效,此时仅根据CacheFullRemoveType在缓存满时替换元素通过protected boolean isExpired(K key)判断某key是否过期
(8)、缓存命中率
getHitRate()、getHitCount()、getMissCount()分别表示缓存命中率、命中次数、未命中次数
(9)、线程池shutdown
public void shutdown()程序结束有需要可以调用shutdown关闭线程池。
(10)、其他与map类似接口
public boolean containsKey(K key) 缓存中是否包含该keypublic CacheObject<V> remove(K key) 从缓存中删除某个keypublic void clear() 清空缓存public Set<K> keySet() 缓存中key集合public Set<Map.Entry<K, CacheObject<V>>> entrySet() 缓存中key,value键值对集合public Collection<CacheObject<V>> values() 缓存中元素集合public CacheObject<V> put(K key, V value) 手动插入某个元素public CacheObject<V> put(K key, CacheObject<V> value) 手动插入某个元素public CacheObject<V> get(K key) 得到某个keypublic int getSize() 得到缓存中有效元素个数public int getMaxSize() 得到缓存中元素最大个数
(11)得到设置
上面的set几乎都可以通过对应的get得到相应value使用getOnGetDataListener()得到获取图片的方法getForwardCacheNumber()得到自动向前缓存的个数getBackCacheNumber()得到自动向后缓存的个数getMaxSize()得到缓存最大容量getValidTime()得到有效时间,以毫秒计getCacheFullRemoveType()得到cache满时删除元素类型
3、其他问题解决
你可能还感兴趣:
转自: