1package com.bumptech.glide.load.model; 2 3import com.bumptech.glide.util.LruCache; 4 5import java.util.ArrayDeque; 6import java.util.Queue; 7 8/** 9 * A simple cache that can be used by {@link ModelLoader} and {@link ModelLoaderFactory} to cache some data for a given 10 * model, width and height. For a loader that takes a model and returns a url, the cache could be used to safely memoize 11 * url creation based on the width and height of the view. 12 * 13 * @param <A> Some Model type that implements equals and hashcode. 14 * @param <B> Some useful type that may be expensive to create (URL, file path, etc). 15 * //TODO: fix this. 16 */ 17public class ModelCache<A, B> { 18 private static final int DEFAULT_SIZE = 250; 19 20 private static class ModelKey<A> { 21 private static final Queue<ModelKey> KEY_QUEUE = new ArrayDeque<ModelKey>(); 22 23 @SuppressWarnings("unchecked") 24 public static <A> ModelKey<A> get(A model, int width, int height) { 25 ModelKey<A> modelKey = KEY_QUEUE.poll(); 26 if (modelKey == null) { 27 modelKey = new ModelKey<A>(); 28 } 29 30 modelKey.init(model, width, height); 31 return modelKey; 32 } 33 34 private int height; 35 private int width; 36 private A model; 37 38 private ModelKey() { } 39 40 private void init(A model, int width, int height) { 41 this.model = model; 42 this.width = width; 43 this.height = height; 44 } 45 46 public void release() { 47 KEY_QUEUE.offer(this); 48 } 49 50 @Override 51 public boolean equals(Object o) { 52 if (this == o) return true; 53 if (o == null || getClass() != o.getClass()) return false; 54 55 ModelKey modelKey = (ModelKey) o; 56 57 if (height != modelKey.height) return false; 58 if (width != modelKey.width) return false; 59 if (!model.equals(modelKey.model)) return false; 60 61 return true; 62 } 63 64 @Override 65 public int hashCode() { 66 int result = height; 67 result = 31 * result + width; 68 result = 31 * result + model.hashCode(); 69 return result; 70 } 71 } 72 73 private final LruCache<ModelKey<A>, B> cache; 74 75 public ModelCache() { 76 this(DEFAULT_SIZE); 77 } 78 79 public ModelCache(int size) { 80 cache = new LruCache<ModelKey<A>, B>(size) { 81 @Override 82 protected void onItemRemoved(ModelKey<A> key, B item) { 83 key.release(); 84 } 85 }; 86 } 87 88 /** 89 * Get a value. 90 * 91 * @param model The model. 92 * @param width The width of the view the image is being loaded into. 93 * @param height The height of the view the image is being loaded into. 94 * 95 * @return The cached result, or null. 96 */ 97 public B get(A model, int width, int height) { 98 ModelKey<A> key = ModelKey.get(model, width, height); 99 B result = cache.get(key); 100 key.release(); 101 return result; 102 } 103 104 /** 105 * Add a value. 106 * 107 * @param model The model. 108 * @param width The width of the view the image is being loaded into. 109 * @param height The height of the view the image is being loaded into. 110 * @param value The value to store. 111 */ 112 public void put(A model, int width, int height, B value) { 113 ModelKey<A> key = ModelKey.get(model, width, height); 114 cache.put(key, value); 115 } 116} 117