自定义ImageLoader

LruCache的原理

                          1>首先理解LinkedHashMap

   理解LinkedHashMap的特性:

   一、可预知的迭代顺序
   二、迭代顺序,该迭代顺序可以是插入顺序或者是访问顺序。
   三、可以重写removeEldestEntry方法返回true值指定插入元素时移除最老的元素。 
           四、默认的情况下removeEldestEntry方法只返回false表示元素永远不过期。

java为数据结构中的映射定义了一个接口java.util.Map;它有四个实现类,分别是HashMap Hashtable LinkedHashMap 和TreeMap.

关于特性使用的方法:

           一、new  LinkedHashMap(10,0.75,true); 前面的两个参数就是HashMap构造函数需要的参数,后面的true表明LinkHashMap按照访问的次序来排序(accessOrder为true);
注意addBefore(lm.header)是将该entry放在header线性表的最后。 (参考LinkedHashMap.Entry extends HashMap.Entry 比起HashMap.Entry多了before, after两个域,是双向的)
           二、

如果removeEldestEntry返回true,那么LinkedHashMap会自动删掉最不常用的那个entry(也就是header线性表最前面的那个)。

这会造成严重的性能问题吗?答案当然是否定的。因为在这儿的链表操作是常量级的。这也是LinkedHashMap/Set在这儿比TreeMap/Set性能更高的原因。

       三、

LinkedHashMap 是HashMap的一个子类,保存了记录的插入顺序,在用Iterator遍历LinkedHashMap时,先得到的记录肯定是先插入的.也可以在构造时用带参数,按照应用次数排序。在遍历的时候会比HashMap慢,不过有种情况例外,当HashMap容量很大,实际数据较少时,遍历起来可能会比 LinkedHashMap慢,因为LinkedHashMap的遍历速度只和实际数据有关,和容量无关,而HashMap的遍历速度和他的容量有关。


                二、LinkedHaspMap与LruCache的关联

一、该哈希映射的迭代顺序就是最后访问其条目的顺序,这种映射很适合构造构建Lru缓存,
LinkedHashMap提供removeEldestEctry(Map.Entry<k,V>    eldest)方法。该方法
提供在每次添加醉酒;
  * 当有新元素加入Map的时候会调用Entry的addEntry方法,会调用removeEldestEntry方法,
  * 这里就是实现LRU元素过期机制的地方,默认的情况下removeEldestEntry方法只返回false表示元素永远不过期。
二、
    if (eldest != header && removeEldestEntry(eldest)) {
        remove(eldest.key);
    }
    ......
	private static final int MAX_ENTRIES = 100;  
	protected boolean removeEldestEntry(Map.Entry eldest) {  
	    return size() > MAX_ENTRIES;  
	}
此方法通常不以任何方式修改映射,相反允许映射在其返回值的指引下进行自我修改。如果用此映射构建LRU缓存,则非常方便,它允许映射通过删除旧条目来减少内存损耗。
      例如:重写此方法,维持此映射只保存100个条目的稳定状态,在每次添加新条目时删除最旧的条目。

LruCache的处理方案优化:
图片被访问的频率有多高?会不会有一些图片的访问频率比其它图片要高?如果有的话,你也许应该让一些图片常驻在内存当中,或者使用多个LruCache 对象来区分不同组的图片。

                     三、LruCache的简介

一、你的设备可以为每个用于程序分配多大的内存?
二、设备屏幕上一次最多能显示多少张图片?有多少张图片需要进行预加载,以为
有可能很快会显示在屏幕上?
三、图片被访问的频率有多高?会不会有一些图片的访问频率比其它图片要高?如果有的话,你也许应该让一些图片常驻在内存当中,或者使用多个LruCache 对象来区分不同组的图片。
四、当向 ImageView 中加载一张图片时,首先会在 LruCache 的缓存中进行检查。如果找到了相应的键值,则会立刻更新ImageView ,否则开启一个后台线程来加载这张图片。

       

自定义ImageLoader


成员变量

1>图片下载的线程池名称

2>图片缓存最大数量

3>图片的KEY缓存

4>图片的缓存

5>图片下载的线程池

6>用于记录图片下载的任务,以便取消

7>图片的总大小


类中的方法

加载图片(load)

异步加载(asyncload)

取消下载(cancel)

从内存中加载[loadFromMemory(String url) ]

从本地设备中加载【loadFromLocal(String url)】

从网络加载图片【loadFormNet(String  url)】

从添加到内存 【addDrawableToMemory(String url,Drawable drawable)】

设置给控件图片 【setImageSafe(final ImageView view,final String url,final Drawable  drawable)】



//从本地设备中加载

一般对图片进行处理有BitmapFactory.decodeByteArray(data,offset,length),BitmapFactory.decodeFile(pathName),

BitmapFactory.decodeStream(is);上面三个分析源码可知,他们都是在Java层创建byte数组,然后把数据传递给本地代码,

而 BitmapFactory.decodeFileDescriptor();

是把文件描述符传递给本地代码,由本地代码去创建图片

注意:

1》内存不足是会把bitmap的数组回收掉,但我们的bitmap不会被回收,当你再次显示的时候,发现bitmap的数组为空时,将会再次根据文件描述符去加载图片,此时可能由于加载耗时造成界面卡顿,但总比OOM要好很多。

2》本地代码在创建图片时,没有对图片进行校验,所以如果文件不完整,或者根本不是一个图片时,系统也不会报错,仍然会返回一个bitmap,但是这个bitmap是一个纯黑色的bitmap;那我们需要在下载图片的时候,一定要先以一个临时文件下载,等下载完毕了,再对图片进行重命名。


//从内存中加载

从内存中获取到了,需要重新放到内存队列的最后

LUC: 一般缓存算法有两种,第一种是LFU,按使用次数来判断删除优先级,使用次数最少的最先删除;还有

一个就是LRC,按照使用时间来判断删除的优先级,最后使用时间越早的最先删除。

这两种算法的原理请看此文章第一节部分。


案例下载:

http://download.csdn.net/detail/javamov/9041621



















                             
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值