In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-02-28 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >
Share
Shulou(Shulou.com)06/02 Report--
一. 前言
图片内存缓存可以提高图片显示速度,但是有些问题,比如占用内存,如果不加以控制,甚至可能会OOM
所以,需要提供各种各样的算法来控制内存的使用,以适应不同的使用场景,目前,ImageLoader提供了若干内存管理算法。
默认内存缓存是关闭的,需要手动打开
二. 继承关系图
三. 主要内存算法介绍算法解释MemoryCacheInterface 内存缓存的接口MemoryCacheInterface 内存缓存的接口FuzzyKeyMemoryCache模糊Key内存缓存,一些不同的Key可能会被认为是相同(通过equals方法)。当你put一个值到cache里面时,equals相同的Key也会被替换。这是一个内部功能,通常我们不需要使用到它。LimitedAgeMemoryCache限制时间内存缓存,如果一些对象的使用时间超过了定义的值,那么就会移除。比如最大时间设置成60s,那么如果一个对象是60s前put进来的,那么它就会失效。LruMemoryCache一个强引用的图片,限制图片使用数量的内存缓存,每个被访问的图片都会移动到队列的头部。当一个图片添加到一个满的队列的时候,队尾的图片将会被驱逐而被垃圾回收器回收。BaseMemoryCache抽象类,基本的图片缓存管理,提供了图片存储(强引用或者弱引用),具体的可以看下面的MemoryCache实现。WeakMemoryCache继承自BaseMemoryCache,弱引用内存缓存,弱引用,当内存不足的时候,会被系统回收。LimitedMemoryCache抽象类,继承自BaseMemoryCache,限制内存的内存管理抽象类,包括下面4个具体实现。提供图片对象存储,存储的所有的图片大小将不会超过大小限制。这个缓存提供了强引用和弱引用存储了图片,强引用用来限制图片大小,弱引用用来其他缓存的图片。FIFOLimitedMemoryCache继承自LimitedMemoryCache,存储的图片大小不小超过限定的大小。当缓存图片到达指定大小时,会按照FIFO(先进先出)的原则清理图片。LRULimitedMemoryCache继承自LimitedMemoryCache,存储的图片大小不小超过限定的大小。当缓存图片到达指定大小时,最早使用的图片会从缓存中删除。LargestLimitedMemoryCache继承自LimitedMemoryCache,存储的图片大小不小超过限定的大小。当缓存图片到达指定大小时,最大的图片会从缓存中删除。UsingFreqLimitedMemoryCache继承自LimitedMemoryCache,存储的图片大小不小超过限定的大小。当缓存图片到达指定大小时,最少使用频率的图片会从缓存中删除。
下面,我们会具体看各个MemoryCache的实现
四. LimitedAgeMemoryCachepublic class LimitedAgeMemoryCache implements MemoryCache { private final MemoryCache cache; private final long maxAge; private final Map loadingDates = Collections.synchronizedMap(new HashMap()); @Override public boolean put(String key, Bitmap value) { boolean putSuccesfully = cache.put(key, value); if (putSuccesfully) { loadingDates.put(key, System.currentTimeMillis()); } return putSuccesfully; } @Override public Bitmap get(String key) { Long loadingDate = loadingDates.get(key); if (loadingDate != null && System.currentTimeMillis() - loadingDate > maxAge) { cache.remove(key); loadingDates.remove(key); } return cache.get(key); }}
实现的方法很简单,在put的时候,用一个Map记录了存入的时间,get的时候,判断时间是否大于maxAge,如果是,那么就删掉这个缓存。
五. LruMemoryCachepublic class LruMemoryCache implements MemoryCache { private final LinkedHashMap map; private final int maxSize; @Override public final boolean put(String key, Bitmap value) { ... synchronized (this) { size += sizeOf(key, value); Bitmap previous = map.put(key, value); if (previous != null) { size -= sizeOf(key, previous); } } 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 sizeLimit) { Bitmap removedValue = removeNext(); if (hardCache.remove(removedValue)) { curCacheSize = cacheSize.addAndGet(-getSize(removedValue)); } } hardCache.add(value); cacheSize.addAndGet(valueSize); putSuccessfully = true; } // Add value to soft cache super.put(key, value); return putSuccessfully; }} public class FIFOLimitedMemoryCache extends LimitedMemoryCache { private final List queue = Collections.synchronizedList(new LinkedList()); ... @Override protected Bitmap removeNext() { return queue.remove(0); }}
用list实现,直接从头开始移除。
八. LRULimitedMemoryCachepublic class LRULimitedMemoryCache extends LimitedMemoryCache { /** Cache providing Least-Recently-Used logic */ private final Map lruCache = Collections.synchronizedMap(new LinkedHashMap(INITIAL_CAPACITY, LOAD_FACTOR, true)); @Override protected Bitmap removeNext() { Bitmap mostLongUsedValue = null; synchronized (lruCache) { Iterator it = lruCache.entrySet().iterator(); if (it.hasNext()) { Entry entry = it.next(); mostLongUsedValue = entry.getValue(); it.remove(); } } return mostLongUsedValue; }}
使用一个 LinkedHashMap lruCache来保存图片的put顺序,需要移除的时候(removeNext)从lruCache找到第一张图片即可。
九. UsingFreqLimitedMemoryCachepublic class UsingFreqLimitedMemoryCache extends LimitedMemoryCache { private final Map usingCounts = Collections.synchronizedMap(new HashMap()); @Override public Bitmap get(String key) { Bitmap value = super.get(key); // Increment usage count for value if value is contained in hardCahe if (value != null) { Integer usageCount = usingCounts.get(value); if (usageCount != null) { usingCounts.put(value, usageCount + 1); } } return value; } @Override protected Bitmap removeNext() { Integer minUsageCount = null; Bitmap leastUsedValue = null; Set entries = usingCounts.entrySet(); synchronized (usingCounts) { for (Entry entry : entries) { if (leastUsedValue == null) { leastUsedValue = entry.getKey(); minUsageCount = entry.getValue(); } else { Integer lastValueUsage = entry.getValue(); if (lastValueUsage < minUsageCount) { minUsageCount = lastValueUsage; leastUsedValue = entry.getKey(); } } } } usingCounts.remove(leastUsedValue); return leastUsedValue; }}
使用一个HashMap usingCounts来存储bitmap的使用次数,每次get的时候都会让使用次数+1,那需要移除的时候图片缓存的时候,遍历usingCounts,找到使用次数最少的图片,删除之。
不过这种遍历的算法感觉效率不高,慎用!
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.