17 package android.util; 18  19 import java.util.LinkedHashMap; 20 import java.util.Map; 21  22 /** 23  * A cache that holds strong references to a limited number of values. Each time 24  * a value is accessed, it is moved to the head of a queue. When a value is 25  * added to a full cache, the value at the end of that queue is evicted and may 26  * become eligible for garbage collection. 
一个cache缓冲区,维护有限个值的强引用。当一个值被命中时,它被移到队列的头部???确定有移动么
当一个值被加入一个已满的cache中时,队列最后一个值被舍弃。可能会被垃圾回收
28 * <p>If your cached values hold resources that need to be explicitly released, 29 * override {@link #entryRemoved}.
如果你缓存的值中有必须被释放的资源,需要override entryRemoved方法
31 * <p>If a cache miss should be computed on demand for the corresponding keys, 32 * override {@link #create}. This simplifies the calling code, allowing it to 33 * assume a value will always be returned, even when there's a cache miss.
如果一次cache未命中时,同样需要返回。 需要override create()方法。
这使调用简化:不管是不是命中,都返回一个值。

因为当前的create方法返回的是个null。当你没get到的时候,会调用create方法。在当前情况下,返回null会直接return null。
不会往后执行之后的创建键值对,并返回的操作。

但是如果你重写了create(),使其返回的不是null,则后边的操作会执行。调用get(key),value值被返回。
35 * <p>By default, the cache size is measured in the number of entries. Override 36 * {@link #sizeOf} to size the cache in different units. For example, this cache 37 * is limited to 4MiB of bitmaps:
默认情况下,一个cache的大小,是以实体的个数来衡量的。因为当前的sizeOf() 方法返回的是1,也就是每个entry大小是1
你可以override sizeof方法,改变cache 的最小单元大小。
例如,下边这个cache 限制为最大4MiB的bitmap cache
每个单元的大小就不是1了,而是bitmap的大小。
38 * <pre> {@code 39 * int cacheSize = 4 * 1024 * 1024; // 4MiB 40 * LruCache<String, Bitmap> bitmapCache = new LruCache<String, Bitmap>(cacheSize) { 41 * protected int sizeOf(String key, Bitmap value) { 42 * return value.getByteCount(); 43 * } 44 * }}</pre>
LRUCache类是线程安全的。多个cache操作时候。要synchronize这个cache

46 * <p>This class is thread-safe. Perform multiple cache operations atomically by 47 * synchronizing on the cache: <pre> {@code 48 * synchronized (cache) { 49 * if (cache.get(key) == null) { 50 * cache.put(key, value); 51 * } 52 * }}</pre>
这个类不允许传入的key和value是空。
get put remove返回null,代表这个key不再cache中

54 * <p>This class does not allow null to be used as a key or value. A return 55 * value of null from {@link #get}, {@link #put} or {@link #remove} is 56 * unambiguous: the key was not in the cache. 57 * 58 * <p>This class appeared in Android 3.1 (Honeycomb MR1); it's available as part 59 * of <a href="http://developer.android.com/sdk/compatibility-library.html">Android's 60 * Support Package</a> for earlier releases. 61 */ 62 public class LruCache<K, V> { 63 private final LinkedHashMap<K, V> map; 64 65 /** Size of this cache in units. Not necessarily the number of elements. */ 66 private int size; 67 private int maxSize; 68 69 private int putCount; 70 private int createCount; 71 private int evictionCount; 72 private int hitCount; 73 private int missCount; 74 75 /** 76 * @param maxSize for caches that do not override {@link #sizeOf}, this is 77 * the maximum number of entries in the cache. For all other caches, 78 * this is the maximum sum of the sizes of the entries in this cache. 79 */ 80 public LruCache(int maxSize) { 81 if (maxSize <= 0) { 82 throw new IllegalArgumentException("maxSize <= 0"); 83 } 84 this.maxSize = maxSize; 85 this.map = new LinkedHashMap<K, V>(0, 0.75f, true); 86 } 87 88 /** 89 * Sets the size of the cache. 90 * @param maxSize The new maximum size. 91 * 92 * @hide 93 */ 94 public void resize(int maxSize) { 95 if (maxSize <= 0) { 96 throw new IllegalArgumentException("maxSize <= 0"); 97 } 98 99 synchronized (this) {100 this.maxSize = maxSize;101 }102 trimToSize(maxSize);103 }104 105 /**106 * Returns the value for {@code key} if it exists in the cache or can be107 * created by {@code #create}. If a value was returned, it is moved to the108 * head of the queue. This returns null if a value is not cached and cannot109 * be created.110 */111 public final V get(K key) {112 if (key == null) {113 throw new NullPointerException("key == null");114 }115 116 V mapValue;117 synchronized (this) {118 mapValue = map.get(key);119 if (mapValue != null) {120 hitCount++;121 return mapValue;122 }123 missCount++;124 }125 126 /*127 * Attempt to create a value. This may take a long time, and the map128 * may be different when create() returns. If a conflicting value was129 * added to the map while create() was working, we leave that value in130 * the map and release the created value.131 */132 133 V createdValue = create(key);134 if (createdValue == null) {135 return null;136 }137 138 synchronized (this) {139 createCount++;140 mapValue = map.put(key, createdValue);141 142 if (mapValue != null) {143 // There was a conflict so undo that last put144 map.put(key, mapValue);145 } else {146 size += safeSizeOf(key, createdValue);147 }148 }149 150 if (mapValue != null) {151 entryRemoved(false, key, createdValue, mapValue);152 return mapValue;153 } else {154 trimToSize(maxSize);155 return createdValue;156 }157 }158 159 /**160 * Caches {@code value} for {@code key}. The value is moved to the head of161 * the queue.162 *163 * @return the previous value mapped by {@code key}.164 */165 public final V put(K key, V value) {166 if (key == null || value == null) {167 throw new NullPointerException("key == null || value == null");168 }169 170 V previous;171 synchronized (this) {172 putCount++;173 size += safeSizeOf(key, value);174 previous = map.put(key, value);175 if (previous != null) {176 size -= safeSizeOf(key, previous);177 }178 }179 180 if (previous != null) {181 entryRemoved(false, key, previous, value);182 }183 184 trimToSize(maxSize);185 return previous;186 }187 188 /**189 * Remove the eldest entries until the total of remaining entries is at or190 * below the requested size.191 *192 * @param maxSize the maximum size of the cache before returning. May be -1193 * to evict even 0-sized elements.194 */195 public void trimToSize(int maxSize) {196 while (true) {197 K key;198 V value;199 synchronized (this) {200 if (size < 0 || (map.isEmpty() && size != 0)) {201 throw new IllegalStateException(getClass().getName()202 + ".sizeOf() is reporting inconsistent results!");203 }204 205 if (size <= maxSize) {206 break;207 }208 209 Map.Entry<K, V> toEvict = map.eldest();210 if (toEvict == null) {211 break;212 }213 214 key = toEvict.getKey();215 value = toEvict.getValue();216 map.remove(key);217 size -= safeSizeOf(key, value);218 evictionCount++;219 }220 221 entryRemoved(true, key, value, null);222 }223 }224 225 /**226 * Removes the entry for {@code key} if it exists.227 *228 * @return the previous value mapped by {@code key}.229 */230 public final V remove(K key) {231 if (key == null) {232 throw new NullPointerException("key == null");233 }234 235 V previous;236 synchronized (this) {237 previous = map.remove(key);238 if (previous != null) {239 size -= safeSizeOf(key, previous);240 }241 }242 243 if (previous != null) {244 entryRemoved(false, key, previous, null);245 }246 247 return previous;248 }249 250 /**251 * Called for entries that have been evicted or removed. This method is252 * invoked when a value is evicted to make space, removed by a call to253 * {@link #remove}, or replaced by a call to {@link #put}. The default254 * implementation does nothing.255 *256 * <p>The method is called without synchronization: other threads may257 * access the cache while this method is executing.258 *259 * @param evicted true if the entry is being removed to make space, false260 * if the removal was caused by a {@link #put} or {@link #remove}.261 * @param newValue the new value for {@code key}, if it exists. If non-null,262 * this removal was caused by a {@link #put}. Otherwise it was caused by263 * an eviction or a {@link #remove}.264 */265 protected void entryRemoved(boolean evicted, K key, V oldValue, V newValue) {}266 267 /**268 * Called after a cache miss to compute a value for the corresponding key.269 * Returns the computed value or null if no value can be computed. The270 * default implementation returns null.271 *272 * <p>The method is called without synchronization: other threads may273 * access the cache while this method is executing.274 *275 * <p>If a value for {@code key} exists in the cache when this method276 * returns, the created value will be released with {@link #entryRemoved}277 * and discarded. This can occur when multiple threads request the same key278 * at the same time (causing multiple values to be created), or when one279 * thread calls {@link #put} while another is creating a value for the same280 * key.281 */282 protected V create(K key) {283 return null;284 }285 286 private int safeSizeOf(K key, V value) {287 int result = sizeOf(key, value);288 if (result < 0) {289 throw new IllegalStateException("Negative size: " + key + "=" + value);290 }291 return result;292 }293 294 /**295 * Returns the size of the entry for {@code key} and {@code value} in296 * user-defined units. The default implementation returns 1 so that size297 * is the number of entries and max size is the maximum number of entries.298 *299 * <p>An entry's size must not change while it is in the cache.300 */301 protected int sizeOf(K key, V value) {302 return 1;303 }304 305 /**306 * Clear the cache, calling {@link #entryRemoved} on each removed entry.307 */308 public final void evictAll() {309 trimToSize(-1); // -1 will evict 0-sized elements310 }311 312 /**313 * For caches that do not override {@link #sizeOf}, this returns the number314 * of entries in the cache. For all other caches, this returns the sum of315 * the sizes of the entries in this cache.316 */317 public synchronized final int size() {318 return size;319 }320 321 /**322 * For caches that do not override {@link #sizeOf}, this returns the maximum323 * number of entries in the cache. For all other caches, this returns the324 * maximum sum of the sizes of the entries in this cache.325 */326 public synchronized final int maxSize() {327 return maxSize;328 }329 330 /**331 * Returns the number of times {@link #get} returned a value that was332 * already present in the cache.333 */334 public synchronized final int hitCount() {335 return hitCount;336 }337 338 /**339 * Returns the number of times {@link #get} returned null or required a new340 * value to be created.341 */342 public synchronized final int missCount() {343 return missCount;344 }345 346 /**347 * Returns the number of times {@link #create(Object)} returned a value.348 */349 public synchronized final int createCount() {350 return createCount;351 }352 353 /**354 * Returns the number of times {@link #put} was called.355 */356 public synchronized final int putCount() {357 return putCount;358 }359 360 /**361 * Returns the number of values that have been evicted.362 */363 public synchronized final int evictionCount() {364 return evictionCount;365 }366 367 /**368 * Returns a copy of the current contents of the cache, ordered from least369 * recently accessed to most recently accessed.370 */371 public synchronized final Map<K, V> snapshot() {372 return new LinkedHashMap<K, V>(map);373 }374 375 @Override public synchronized final String toString() {376 int accesses = hitCount + missCount;377 int hitPercent = accesses != 0 ? (100 * hitCount / accesses) : 0;378 return String.format("LruCache[maxSize=%d,hits=%d,misses=%d,hitRate=%d%%]",379 maxSize, hitCount, missCount, hitPercent);380 }381 }

更多相关文章

  1. Android利用资源名称获取其id之getIdentifier()方法
  2. asynchttpclient的post方法发送json格式参数和表单格式参数
  3. Android中button的onClick事件几种方法
  4. Android 关闭多个Activity的实现方法
  5. Android中几种延后处理事件的方法
  6. Android判断包名和类名是否存在的方法
  7. Android SDK 1.5 "--core-library" build error问题解决方法
  8. android http通信(二) 英译汉字典实例探究网络通信三种方法

随机推荐

  1. Android(安卓)计算两个地理坐标之间的距
  2. Android Q : 安卓源码、水滴屏适配状态栏
  3. Android 中文 API (21) ―― DigitalClock
  4. Android 教你如何通过 LocationManager
  5. android中实现从一个图片中截取一部分,在
  6. android layout属性 .
  7. Android模仿文件夹管理实例
  8. Android画图学习笔记一 类的简介
  9. android录音相关
  10. Android(安卓)Enter软件盘监听事件。