Android开源项目 Universal imageloader 源码研究之Lru算法
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算法的更多相关文章
- Android开源项目 Universal imageloader 源码研究之项目框架
Universal imageloader 的代码并不复杂 重点是缓存,线程池任务 下面都用UML图进行了绘制 基本使用流程就是 初始化配置,设置Options参数,最后Dispaly提交下载 pub ...
- 谷歌开源项目Chromium的源码获取与项目构建(Win7+vs10/vs13)
转自:http://blog.csdn.net/kuerjinjin/article/details/23563059 从12年那会儿开始获取源码和构建chromium项目都是按照那时候的官方要求用w ...
- Android开源git40个App源码
http://www.itbbu.com/1039.html (JamsMusicPlayer)很棒的音乐播放器(new) (F8)日程安排的软件 (Conversations)基于XMPP的 ...
- Android 开源项目源码解析(第二期)
Android 开源项目源码解析(第二期) 阅读目录 android-Ultra-Pull-To-Refresh 源码解析 DynamicLoadApk 源码解析 NineOldAnimations ...
- 10个经典的Android开源项目(附源码包)
最近在抽空学习Android系统开发,对Android学习也比较感兴趣,刚开始学就试着在网上找几个项目源码研究看下,以下就将找到的Android项目源码列出,希望对正在或准备学习Android系统开发 ...
- 从源码研究如何不重启Springboot项目实现redis配置动态切换
上一篇Websocket的续篇暂时还没有动手写,这篇算是插播吧.今天讲讲不重启项目动态切换redis服务. 背景 多个项目或微服务场景下,各个项目都需要配置redis数据源.但是,每当运维搞事时(修改 ...
- 59.Android开源项目及库 (转)
转载 : https://github.com/Tim9Liu9/TimLiu-Android?hmsr=toutiao.io&utm_medium=toutiao.io&utm_so ...
- GitHub 优秀的 Android 开源项目(转)
今天查找资源时看到的一篇文章,总结了很多实用资源,十分感谢原作者分享. 转自:http://blog.csdn.net/shulianghan/article/details/18046021 主要介 ...
- GitHub 优秀的 Android 开源项目
转自:http://blog.csdn.net/shulianghan/article/details/18046021 主要介绍那些不错个性化的View,包括ListView.ActionBar.M ...
随机推荐
- ctr预估模型
http://wenku.baidu.com/course/view/1488bfd5b9f3f90f76c61b8d
- BAT互联网公司是如何内部推荐的?
中国十大互联网公司 注:以上按照目前市值排序整理出来,当然还有更多未上市的潜力股.如:美团.豆瓣.豌豆荚.美图秀秀等等 各大互联网公司招聘官网 阿里招聘:https://job.alibaba.com ...
- java学习面向对象之继承
在我们编写程序的过程当中,会遇到这种情况: 比如现在有一个狗,他的功能有跑,有跳,有吃,有叫,属性有雌雄,大小,颜色等等,同时现在我们也有一个猫,上述功能她也有.这个时候我们写代码的时候,就得分别把上 ...
- Linux企业级开发技术(3)——epoll企业级开发之epoll模型
EPOLL事件有两种模型: Edge Triggered (ET) 边缘触发 只有数据到来,才触发,不管缓存区中是否还有数据. Level Triggered (LT) 水平触发 只要有数据都会触 ...
- POJ3617 Best Cow Line
其实是学习参考了算法书的代码,但仍然是我自己写的,有小差别.贪心类型. #include <iostream> using namespace std; int main() { int ...
- poj2325
题目大意描述: 题目:固执的数??持久的数?? 2014/12/06 18:41 数字乘法的持久性由 Neil Sloane定义, (Neil Sloane在一个娱乐杂志上发表关于数字持久性的文章 6 ...
- TCP具体解释(3):重传、流量控制、拥塞控制……
传输数据 在TCP的数据传送状态.非常多重要的机制保证了TCP的可靠性和强壮性.它们包括:使用序号.对收到的TCP报文段进行排序以及检測反复的数据:使用校验和来检測报文段的错误.使用确认和计时器来检測 ...
- JAVA中的继承和覆盖
java里面的继承是子类继承父类的一些方法和属性(除private属性和方法之外):对于父类的私有属性和方法子类是没有继承的.可是要想子类也能訪问到父类的私有属性,必须给私有属性以外界訪问的方法接口. ...
- Oracle内存结构(之三)
[深入解析--eygle] 学习笔记 1.2.3 PGA的管理: sys@felix SQL>show parameter area_size NAME TYPE VALUE --------- ...
- 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 ...