https://github.com/nostra13/Android-Universal-Image-Loader

universal imageloader 源码研究之Lru算法

LRU - Least Recently Used 最近最少使用算法

字面意思就是在数据队列里面 最少使用的优先移除,腾出空间 提高任务调度,

接口
com.nostra13.universalimageloader.cache.memory.MemoryCache

实现
com.nostra13.universalimageloader.cache.memory.impl.LruMemoryCache

上面的是内存中最近最少使用的数据 将会移除从内存中。

通过 com.nostra13.universalimageloader.core.ImageLoaderConfiguration 可以设置cacheSize

    ImageLoaderConfiguration configuration = new  ImageLoaderConfiguration.Builder(context)
.memoryCacheSize(10 * 1024 * 1024) // 10MB 大小
.build();
ImageLoader imageloader = ImageLoader.getInstance();
imageloader.init(configuration);

如果客户端没有主动设置cacheSize 将会创建一个默认的大小
com.nostra13.universalimageloader.core.DefaultConfigurationFactory

    public static MemoryCache createMemoryCache(Context context, int memoryCacheSize) {
if (memoryCacheSize == 0) {
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
int memoryClass = am.getMemoryClass(); //这个返回一个APK的heap最大值限制
if (hasHoneycomb() && isLargeHeap(context)) {
memoryClass = getLargeMemoryClass(am);
}
memoryCacheSize = 1024 * 1024 * memoryClass / 8; // 取 1/8 大小内存, 如果是128MB cacheSize为16MB大小
}
return new LruMemoryCache(memoryCacheSize);
}
    // am.getMemoryClass(); 我的PAD打印是128MB
static public int staticGetMemoryClass() {
// Really brain dead right now -- just take this from the configured
// vm heap size, and assume it is in megabytes and thus ends with "m".
String vmHeapSize = SystemProperties.get("dalvik.vm.heapgrowthlimit", "");
if (vmHeapSize != null && !"".equals(vmHeapSize)) {
return Integer.parseInt(vmHeapSize.substring(0, vmHeapSize.length()-1));
}
return staticGetLargeMemoryClass();
}

看看  LruMemoryCache

    public LruMemoryCache(int maxSize) { //初始化大小
if (maxSize <= 0) {
throw new IllegalArgumentException("maxSize <= 0");
}
this.maxSize = maxSize;
this.map = new LinkedHashMap<String, Bitmap>(0, 0.75f, true); //LinkedHashMap 数据结构
//注意 第三个参数为true表示 每次执行put和get会把对应的Entry移到最新位置,如果设置为false 位置不会变化 会导致移除的对象为第一个put的对象
/**
* 比如顺序: put(01,bitmap), put(02,bitmap) put(03,bitmap) put(01,bitmap)
* 如果设置为true会移除掉 key=02的数据
* 如果设置为false会移除掉key=01的数据,但是01的数据 最后又更新了,显然不符合LRU的特点
* 如果调用了get方法 也会把item位置更新到最新,这样没有被调用的数据 就排在最后 可能会被移除掉
* MAP 迭代的话 第一个元素就是 最少使用的对象
*/
}
    public final boolean put(String key, Bitmap value) {
if (key == null || value == null) {
throw new NullPointerException("key == null || value == null");
} synchronized (this) {
size += sizeOf(key, value); //开始计算大小
Bitmap previous = map.put(key, value); //之前有重复的key 取出对象 ,put函数返回上次已经存储key对应的值
if (previous != null) {
size -= sizeOf(key, previous); //减去以前的对象大小,因为已经被新的value覆盖了
}
} trimToSize(maxSize); //尝试移除工作
return true;
}
    private void trimToSize(int maxSize) {
while (true) {
String key;
Bitmap value;
synchronized (this) {
if (size < 0 || (map.isEmpty() && size != 0)) {
throw new IllegalStateException(getClass().getName() + ".sizeOf() is reporting inconsistent results!");
} if (size <= maxSize || map.isEmpty()) { //如果中大小没有超过cacheSize 不需要移除任何对象
break;
} Map.Entry<String, Bitmap> toEvict = map.entrySet().iterator().next(); //取最少使用的Item数据
if (toEvict == null) {
break;
}
key = toEvict.getKey();
value = toEvict.getValue();
map.remove(key); //移除最近最少使用的
size -= sizeOf(key, value); //更新内存中的 size 大小
}
}
}

移除所有

trimToSize(-1) 这样就OK了。

以前用2个HashMap来实现过LRU ,就是其中一个HashMap存储使用最近的时间,只要调用get被使用 就更新一下当前时间。移除对象的时候 根据时间排序移除时间最老的 也是OK的,但是没有把内存大小算进去。

Android开源项目 Universal imageloader 源码研究之Lru算法的更多相关文章

  1. Android开源项目 Universal imageloader 源码研究之项目框架

    Universal imageloader 的代码并不复杂 重点是缓存,线程池任务 下面都用UML图进行了绘制 基本使用流程就是 初始化配置,设置Options参数,最后Dispaly提交下载 pub ...

  2. 谷歌开源项目Chromium的源码获取与项目构建(Win7+vs10/vs13)

    转自:http://blog.csdn.net/kuerjinjin/article/details/23563059 从12年那会儿开始获取源码和构建chromium项目都是按照那时候的官方要求用w ...

  3. Android开源git40个App源码

    http://www.itbbu.com/1039.html (JamsMusicPlayer)很棒的音乐播放器(new)   (F8)日程安排的软件   (Conversations)基于XMPP的 ...

  4. Android 开源项目源码解析(第二期)

    Android 开源项目源码解析(第二期) 阅读目录 android-Ultra-Pull-To-Refresh 源码解析 DynamicLoadApk 源码解析 NineOldAnimations ...

  5. 10个经典的Android开源项目(附源码包)

    最近在抽空学习Android系统开发,对Android学习也比较感兴趣,刚开始学就试着在网上找几个项目源码研究看下,以下就将找到的Android项目源码列出,希望对正在或准备学习Android系统开发 ...

  6. 从源码研究如何不重启Springboot项目实现redis配置动态切换

    上一篇Websocket的续篇暂时还没有动手写,这篇算是插播吧.今天讲讲不重启项目动态切换redis服务. 背景 多个项目或微服务场景下,各个项目都需要配置redis数据源.但是,每当运维搞事时(修改 ...

  7. 59.Android开源项目及库 (转)

    转载 : https://github.com/Tim9Liu9/TimLiu-Android?hmsr=toutiao.io&utm_medium=toutiao.io&utm_so ...

  8. GitHub 优秀的 Android 开源项目(转)

    今天查找资源时看到的一篇文章,总结了很多实用资源,十分感谢原作者分享. 转自:http://blog.csdn.net/shulianghan/article/details/18046021 主要介 ...

  9. GitHub 优秀的 Android 开源项目

    转自:http://blog.csdn.net/shulianghan/article/details/18046021 主要介绍那些不错个性化的View,包括ListView.ActionBar.M ...

随机推荐

  1. ctr预估模型

    http://wenku.baidu.com/course/view/1488bfd5b9f3f90f76c61b8d

  2. BAT互联网公司是如何内部推荐的?

    中国十大互联网公司 注:以上按照目前市值排序整理出来,当然还有更多未上市的潜力股.如:美团.豆瓣.豌豆荚.美图秀秀等等 各大互联网公司招聘官网 阿里招聘:https://job.alibaba.com ...

  3. java学习面向对象之继承

    在我们编写程序的过程当中,会遇到这种情况: 比如现在有一个狗,他的功能有跑,有跳,有吃,有叫,属性有雌雄,大小,颜色等等,同时现在我们也有一个猫,上述功能她也有.这个时候我们写代码的时候,就得分别把上 ...

  4. Linux企业级开发技术(3)——epoll企业级开发之epoll模型

    EPOLL事件有两种模型: Edge Triggered (ET)  边缘触发 只有数据到来,才触发,不管缓存区中是否还有数据. Level Triggered (LT)  水平触发 只要有数据都会触 ...

  5. POJ3617 Best Cow Line

    其实是学习参考了算法书的代码,但仍然是我自己写的,有小差别.贪心类型. #include <iostream> using namespace std; int main() { int ...

  6. poj2325

    题目大意描述: 题目:固执的数??持久的数?? 2014/12/06 18:41 数字乘法的持久性由 Neil Sloane定义, (Neil Sloane在一个娱乐杂志上发表关于数字持久性的文章 6 ...

  7. TCP具体解释(3):重传、流量控制、拥塞控制……

    传输数据 在TCP的数据传送状态.非常多重要的机制保证了TCP的可靠性和强壮性.它们包括:使用序号.对收到的TCP报文段进行排序以及检測反复的数据:使用校验和来检測报文段的错误.使用确认和计时器来检測 ...

  8. JAVA中的继承和覆盖

    java里面的继承是子类继承父类的一些方法和属性(除private属性和方法之外):对于父类的私有属性和方法子类是没有继承的.可是要想子类也能訪问到父类的私有属性,必须给私有属性以外界訪问的方法接口. ...

  9. Oracle内存结构(之三)

    [深入解析--eygle] 学习笔记 1.2.3 PGA的管理: sys@felix SQL>show parameter area_size NAME TYPE VALUE --------- ...

  10. rsyslog 报 WARNING: rsyslogd is running in compatibility mode.

      [root@localhost log]# uname -a Linux localhost.localdomain 2.6.32 #1 SMP Sun Sep 20 18:58:21 PDT 2 ...