本文主要介绍一个支持图片自动预取、支持多种缓存算法的图片缓存的使用及功能。图片较大需要SD卡保存情况推荐使用ImageSDCardCache

与Android LruCache相比主要特性:(1).  使用简单   (2). 轻松获取及预取新图片  (3).  可选择多种缓存算法(FIFO、LIFO、LRU、MRU、LFU、MFU等13种)或自定义缓存算法   (4).  省流量性能佳(有且仅有一个线程获取图片)   (5).  支持不同类型网络处理  (6).  可根据系统配置初始化缓存  (7).  扩展性强   (8).  支持队列   (9).   包含map的大多数接口。

适用:获取图片较多且图片不大的应用,如新浪微博、twitter、微信头像、美丽说、蘑菇街、花瓣、淘宝等等。

本文以用ImageCache实现瀑布流为例,示例APK地址见Demo.apk,示例代码地址见ImageCacheDemo,效果图如下:

1、使用

(1)引入公共库

引入TrineaAndroidCommon@Github(欢迎star和fork^_^)或TrineaAndroidCommon@GoogleCode作为你项目的library(如何拉取代码及添加公共库),或是自己抽取其中的ImageCache@GithubImageCache@GoogleCode部分使用。

(2)调用

仅需简单两步:定义缓存和回调接口、调用get(String imageUrl, View view)异步加载图片。

 
 

Java

 
 
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);
}

需要加载图片的地方调用

 
 

Java

 
 
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表示会被先删除

 
 

Java

 
 
1
2
3
4
5
6
7
8
9
public class RemoveTypePriorityHigh&lt;T&gt; implements CacheFullRemoveType&lt;T&gt; {
 
    private static final long serialVersionUID = 1L;
 
    @Override
    public int compare(CacheObject&lt;T&gt; obj1, CacheObject&lt;T&gt; obj2) {
        return (obj2.getPriority() &gt; 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) 缓存中是否包含该key
public CacheObject<V> remove(K key) 从缓存中删除某个key
public 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) 得到某个key
public int getSize() 得到缓存中有效元素个数
public int getMaxSize() 得到缓存中元素最大个数

(11)得到设置
上面的set几乎都可以通过对应的get得到相应value
使用getOnGetDataListener()得到获取图片的方法
getForwardCacheNumber()得到自动向前缓存的个数
getBackCacheNumber()得到自动向后缓存的个数
getMaxSize()得到缓存最大容量
getValidTime()得到有效时间,以毫秒计
getCacheFullRemoveType()得到cache满时删除元素类型

3、其他问题解决
ListView滑动过程中图片显示重复错乱闪烁问题解决
图片OutOfMemory异常bitmap size exceeds VM budget的原因及解决方法

你可能还感兴趣:

Android系统下载管理DownloadManager功能介绍及使用示例

Android性能调优总结

下拉刷新及滚动到底部加载更多的Listview使用

PreloadDataCache 预取数据缓存

转自:链接

Android ImageCache图片缓存,使用简单,支持预取,支持多种缓存算法,支持不同网络类型,扩展性强的更多相关文章

  1. 【Java/Android性能优5】 Android ImageCache图片缓存,使用简单,支持预取,支持多种缓存算法,支持不同网络类型,扩展性强

    本文转自:http://www.trinea.cn/android/android-imagecache/ 主要介绍一个支持图片自动预取.支持多种缓存算法.支持二级缓存.支持数据保存和恢复的图片缓存的 ...

  2. 【Java/Android性能优 4】PreloadDataCache支持预取的数据缓存,使用简单,支持多种缓存算法,支持不同网络类型,扩展性强

    本文转自:http://www.trinea.cn/android/preloaddatacache/ 本文主要介绍一个支持自动向前或向后获取新数据的缓存的使用及功能.Android图片内存缓存可见I ...

  3. Android批量图片载入经典系列——使用LruCache、AsyncTask缓存并异步载入图片

    一.问题描写叙述 使用LruCache.AsyncTask实现批量图片的载入并达到下列技术要求 1.从缓存中读取图片,若不在缓存中,则开启异步线程(AsyncTask)载入图片,并放入缓存中 2.及时 ...

  4. Android批量图片加载经典系列——使用xutil框架缓存、异步加载网络图片

    一.问题描述 为提高图片加载的效率,需要对图片的采用缓存和异步加载策略,编码相对比较复杂,实际上有一些优秀的框架提供了解决方案,比如近期在git上比较活跃的xutil框架 Xutil框架提供了四大模块 ...

  5. 【Java/Android性能优 6】Android 图片SD卡缓存 使用简单 支持预取 支持多种缓存算法 支持不同网络类型 支持序列化

    本文转自:http://www.trinea.cn/android/android-imagesdcardcache/ 本文主要介绍一个支持图片自动预取.支持多种缓存算法.支持数据保存和恢复的图片Sd ...

  6. 【MDCC 2015】开源选型之Android三大图片缓存原理、特性对比

    摘要:这是快的打车移动端架构师.Android 开源项目源码解析codeKK发起人 吴更新(@Trinea)在MDCC上分享的内容,从总体设计和原理上对几个图片缓存进行对比,没用到它们的朋友也可以了解 ...

  7. 65.Android 三大图片缓存原理、特性对比 (转)

    这是 Trinea 在 MDCC 上分享的内容(略微改动),也是源码解析第一期发布时介绍的源码解析后续会慢慢做的事. 从总体设计和原理上对几个图片缓存进行对比,没用到他们的朋友也可以了解他们在某些特性 ...

  8. Android四大图片缓存(Imageloader,Picasso,Glide,Fresco)原理、特性对比

    四大图片缓存基本信息 Universal ImageLoader 是很早开源的图片缓存,在早期被很多应用使用. Picasso 是 Square 开源的项目,且他的主导者是 JakeWharton,所 ...

  9. Android 三大图片缓存原理、特性对比

    这是我在 MDCC 上分享的内容(略微改动),也是源码解析第一期发布时介绍的源码解析后续会慢慢做的事. 从总体设计和原理上对几个图片缓存进行对比,没用到他们的朋友也可以了解他们在某些特性上的实现. 上 ...

随机推荐

  1. IPC----消息队列

    消息队列可以认为是一个消息链表,System V 消息队列使用消息队列标识符标识.具有足够特权的任何进程都可以往一个队列放置一个消息,具有足够特权的任何进程都可以从一个给定队列读出一个消息.在某个进程 ...

  2. jsp调用java方法 function taglib

    1.新建tld文件: my-functions.tld: <?xml version="1.0" encoding="UTF-8"?> <ta ...

  3. effective c++ resources

    http://www.cnblogs.com/littlethank/archive/2011/12/15/2288787.html http://www.cnblogs.com/liao-xiao- ...

  4. poj1177

    题意:在平面直角坐标系内给出一些与坐标轴平行的矩形,将这些矩形覆盖的区域求并集,然后问这个区域的周长是多少.(边与边重合的地方不计入周长) 分析:线段树.曾经做过类似的求矩形覆盖的总面积的题.这道题同 ...

  5. apache官网怎样下载apache HTTP Server服务器

    我相信有些朋友刚用apache服务器时,都希望从官网上下载,而面对着官网上众多的项目和镜像以及目录,也许有点茫然.下面是具体步骤 第一步:打开apache官网 第二步:点击右上角Download,出现 ...

  6. Effective C++ -----条款40:明智而审慎地使用多重继承

    多重继承比单一继承复杂.它可能导致新的歧义性,以及对virtual继承的需要. virtual继承会增加大小.速度.初始化(及赋值)复杂度等等成本.如果virtual base classes不带任何 ...

  7. log4j:WARN No appenders could be found for logger

    直接写我的解决办法: 在src下面新建file名为log4j.properties内容如下:# Configure logging for testing: optionally with log f ...

  8. 【xml】利用OpenCV解析

    看到一篇讲的很清楚的博客:http://blog.csdn.net/jarvischu/article/details/8481510

  9. 用SSH登录局域网中使用网络设置为NAT的虚拟机中的linux

    环境描述: A客户机,安装有putty软件使用SSH方式登录B主机中的虚拟机中的linux:A机的网络地址:192.168.1.2 B主机为Windows7平台,B主机的网络地址为:192.168.1 ...

  10. UICollectionView cellForItemAtIndexPath 方法不走

    在storyboard 中 UICollectionView cellForItemAtIndexPath not called 被坑了好久,各种问题点查找,终于解决了 解决办法: self.auto ...