ImageLoader开源项目学习
2015-06-30 11:24
197 查看
2015-6-29
自打毕业入行就开始了android开发之旅,经历了两三个比较大型的项目。虽然说是大型项目,其实没有多大技术含量,只不过是项目的周期比较长久罢了。在做项目的过程中遇到过几个比较棘手的问题,内存管理就是其中之一。为此,也有牛人专门分享了几个开源框架供大家使用。其中比较流行的就有ImageLoader项目,上次还了解到facebook也开源了一个android图片库的项目叫Fresco。感叹牛人无私奉献的同时,也自省我为什么做不出这样大众化的产品或者框架呢?小说里面常讲成为武林高手,必先有武林秘笈,再通过勤学苦练方能做到。在我们软件行业呢,我认为这“武林秘笈”就是一个个优秀的开源项目。所以,要想成为软件大师,必先深入的研究学习这些项目的源码。以上只是个人的一些经历和看法,此际。
-------------------------我是分割线------------------------
通过ImageLoader项目的学习,希望能搞清楚一件事。那就是ImageLoader的缓存机制。
面试过程中,我问过很多人关于缓存机制的描述,没有一个是满意的。很多人会讲,bitmap不用的时候就回收。我觉得这个描述太浅显了,不足以形容一个机制!所以,通过此文希望能把这个缓存机制描述清楚。
第一个点:内存分配数量
我们都知道java虚拟机分配给每个进程的堆内存(heap limit)是有限的,android也是同样的原理。android当中,每个app的最大内存数跟设备内存是直接联系的。那么,我们实际设备的每个app的最大内存数量能是多少呢?可以通过以下方式获取查看(学习自com.nostra13.universalimageloader.core包下,DefaultConfigurationFactory类的createMemoryCache方法)
并且在android3.0之后,manifest,application增加了一个属性largeHeap。这个设置可以帮助我们app获取更多的内存数量,可以通过以下方式查看
是不是又学了一招?实际效果还没有对比,如果你的程序经常内存溢出,不妨加这个设置试试看。
2015-6-30
补充上一点:经过测试largeMemoryClass最大可达到手机理论内存的1/4(测试型号s3、m8),大大提升了单个app的内存上限。
2015-7-2
第二个点:缓存是如何被及时回收的?
ImageLoader的缓存机制使用的双层缓存,即磁盘、内存缓存。这应该是成熟缓存机制的标配。那么,就先来看看磁盘缓存的文件回收机制吧!
首先,ImageLoader会约定两个数量上限(文件总大小、文件数),只要磁盘文件超过其中之一个上限,就会回收不常用的文件。
那么问题又来了,如何判定一个文件不常用呢?
答案是ImageLoader采用LRU策略(算法)来管理本地磁盘文件。 LRU是Least Recently Used的缩写,即最近最少使用页面置换算法。更详细的LRU策略解释这里不再展开。下面来看看具体实现细节:
LruDiskCache包含一个DiskLruCache的属性,LruDiskCache的接口实现都是依靠DiskLruCache来做的。所以DiskLruCache类里面才是磁盘缓存处理的核心类。DiskLruCache这个类里面有一个File属性journalFile是用来记录文件最近访问先后顺序的。lruEntries属性存放所有磁盘缓存文件的路径和文件大小。lruEntries的定义如下:
第三个参数true就是指按着最经访问顺序来排序。
磁盘缓存就记录这么多,接下来是内存缓存。相信其原理也是类似的。
2015-7-3
本来想内存缓存可能会用到非常巧妙的方法来处理内存的回收问题。查看到结果,有些诧异呢!内存缓存原理:
1、根据url从内存缓存找Bitmap对象,找到返回,否则执行下一步
2、从网络或者磁盘文件读取到Bitmap对象,直接放在一个map容器(使用LRU策略管理)缓存起来并返回。
3、如果容器内的所有Bitmap对象大小超过内存缓存上限maxSize,则remove掉距离当前最久访问的Bitmap对象。(这里就是我说的诧异点,竟然不做recycle操作)
下面是内存缓存管理的类图:
trimToSize方法就是根据内存缓存上限管理的实现。可以看到这里被remove掉的Bitmap对象并没有做recycle操作,而仅仅是被抛弃为垃圾对象等待系统回收,这样还是会留下OOM的隐患。实际上在这里直接做recycle操作是有些鲁莽的,因为这个Bitmap对象很有可能正在被某个view使用中。如果强行recycle,就会报这样一个错:java.lang.RuntimeException:
Canvas: trying to use a recycled bitmap android.graphics.Bitmap。
以上是ImageLoader项目采用的默认缓存策略,该项目还支持FIFO(先进先出)、LimitedAge(最大存储周期)==缓存机制,这里不再做详细记录。缓存的内容就记录这些。
自打毕业入行就开始了android开发之旅,经历了两三个比较大型的项目。虽然说是大型项目,其实没有多大技术含量,只不过是项目的周期比较长久罢了。在做项目的过程中遇到过几个比较棘手的问题,内存管理就是其中之一。为此,也有牛人专门分享了几个开源框架供大家使用。其中比较流行的就有ImageLoader项目,上次还了解到facebook也开源了一个android图片库的项目叫Fresco。感叹牛人无私奉献的同时,也自省我为什么做不出这样大众化的产品或者框架呢?小说里面常讲成为武林高手,必先有武林秘笈,再通过勤学苦练方能做到。在我们软件行业呢,我认为这“武林秘笈”就是一个个优秀的开源项目。所以,要想成为软件大师,必先深入的研究学习这些项目的源码。以上只是个人的一些经历和看法,此际。
-------------------------我是分割线------------------------
通过ImageLoader项目的学习,希望能搞清楚一件事。那就是ImageLoader的缓存机制。
面试过程中,我问过很多人关于缓存机制的描述,没有一个是满意的。很多人会讲,bitmap不用的时候就回收。我觉得这个描述太浅显了,不足以形容一个机制!所以,通过此文希望能把这个缓存机制描述清楚。
第一个点:内存分配数量
我们都知道java虚拟机分配给每个进程的堆内存(heap limit)是有限的,android也是同样的原理。android当中,每个app的最大内存数跟设备内存是直接联系的。那么,我们实际设备的每个app的最大内存数量能是多少呢?可以通过以下方式获取查看(学习自com.nostra13.universalimageloader.core包下,DefaultConfigurationFactory类的createMemoryCache方法)
//获取每个app的最大内存数 ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); int memoryClass = am.getMemoryClass();
并且在android3.0之后,manifest,application增加了一个属性largeHeap。这个设置可以帮助我们app获取更多的内存数量,可以通过以下方式查看
am.getLargeMemoryClass();
是不是又学了一招?实际效果还没有对比,如果你的程序经常内存溢出,不妨加这个设置试试看。
2015-6-30
补充上一点:经过测试largeMemoryClass最大可达到手机理论内存的1/4(测试型号s3、m8),大大提升了单个app的内存上限。
2015-7-2
第二个点:缓存是如何被及时回收的?
ImageLoader的缓存机制使用的双层缓存,即磁盘、内存缓存。这应该是成熟缓存机制的标配。那么,就先来看看磁盘缓存的文件回收机制吧!
首先,ImageLoader会约定两个数量上限(文件总大小、文件数),只要磁盘文件超过其中之一个上限,就会回收不常用的文件。
那么问题又来了,如何判定一个文件不常用呢?
答案是ImageLoader采用LRU策略(算法)来管理本地磁盘文件。 LRU是Least Recently Used的缩写,即最近最少使用页面置换算法。更详细的LRU策略解释这里不再展开。下面来看看具体实现细节:
LruDiskCache包含一个DiskLruCache的属性,LruDiskCache的接口实现都是依靠DiskLruCache来做的。所以DiskLruCache类里面才是磁盘缓存处理的核心类。DiskLruCache这个类里面有一个File属性journalFile是用来记录文件最近访问先后顺序的。lruEntries属性存放所有磁盘缓存文件的路径和文件大小。lruEntries的定义如下:
//这是lru算法的关键所在,以元素最近访问的先后顺序来排序。最近访问的时间距离现在越久则越靠前,否则越靠后 private final LinkedHashMap<String, Entry> lruEntries = new LinkedHashMap<String, Entry>(0, 0.75f, true);
第三个参数true就是指按着最经访问顺序来排序。
磁盘缓存就记录这么多,接下来是内存缓存。相信其原理也是类似的。
2015-7-3
本来想内存缓存可能会用到非常巧妙的方法来处理内存的回收问题。查看到结果,有些诧异呢!内存缓存原理:
1、根据url从内存缓存找Bitmap对象,找到返回,否则执行下一步
2、从网络或者磁盘文件读取到Bitmap对象,直接放在一个map容器(使用LRU策略管理)缓存起来并返回。
3、如果容器内的所有Bitmap对象大小超过内存缓存上限maxSize,则remove掉距离当前最久访问的Bitmap对象。(这里就是我说的诧异点,竟然不做recycle操作)
下面是内存缓存管理的类图:
trimToSize方法就是根据内存缓存上限管理的实现。可以看到这里被remove掉的Bitmap对象并没有做recycle操作,而仅仅是被抛弃为垃圾对象等待系统回收,这样还是会留下OOM的隐患。实际上在这里直接做recycle操作是有些鲁莽的,因为这个Bitmap对象很有可能正在被某个view使用中。如果强行recycle,就会报这样一个错:java.lang.RuntimeException:
Canvas: trying to use a recycled bitmap android.graphics.Bitmap。
以上是ImageLoader项目采用的默认缓存策略,该项目还支持FIFO(先进先出)、LimitedAge(最大存储周期)==缓存机制,这里不再做详细记录。缓存的内容就记录这些。
相关文章推荐
- OC-设计模式KVC+KVO定义及使用
- To Find or Update customer primary Address in Ax 2012
- 代码实现android手机信号监听
- Android高效显示图片详解(二)
- springMVC+Hibernate的配置
- What is Complex Event Processing? (Part 1)
- dubbo+zookeeper小例子
- Android系列---JSON数据解析
- Shell脚本学习
- 2015-06-29
- 深入理解SQL的四种连接-左外连接、右外连接、内连接、全连接
- ArduinoYun教程之Arduino编程环境搭建
- 安卓有道词典开发实例
- Nagios 监控redis
- 06-图7. How Long Does It Take (25)
- easyui-datagrid高度放大或缩小动态设置分页参数
- Jquery操作DOM
- window命令修改ip,dns,查看适配器名称
- Python读写Redis数据库
- pip指定安装包版本