19fc12334a7d14347cd6951d0653264b2597bd3a0Sam Juddpackage com.bumptech.glide.load.model;
2425a2365cb61957bc52ae64ea7caa5f851c7bc72Sam Judd
39aa6dd1e9e9497e54d38a8f5f686dd510b224ee1Sam Juddimport com.bumptech.glide.util.LruCache;
4425a2365cb61957bc52ae64ea7caa5f851c7bc72Sam Judd
578bad2aa32f824f9e098b5058dfa3506a7ed3f62Sam Juddimport java.util.ArrayDeque;
678bad2aa32f824f9e098b5058dfa3506a7ed3f62Sam Juddimport java.util.Queue;
778bad2aa32f824f9e098b5058dfa3506a7ed3f62Sam Judd
8425a2365cb61957bc52ae64ea7caa5f851c7bc72Sam Judd/**
9425a2365cb61957bc52ae64ea7caa5f851c7bc72Sam Judd * A simple cache that can be used by {@link ModelLoader} and {@link ModelLoaderFactory} to cache some data for a given
10425a2365cb61957bc52ae64ea7caa5f851c7bc72Sam Judd * model, width and height. For a loader that takes a model and returns a url, the cache could be used to safely memoize
11425a2365cb61957bc52ae64ea7caa5f851c7bc72Sam Judd * url creation based on the width and height of the view.
12425a2365cb61957bc52ae64ea7caa5f851c7bc72Sam Judd *
1378bad2aa32f824f9e098b5058dfa3506a7ed3f62Sam Judd * @param <A> Some Model type that implements equals and hashcode.
1478bad2aa32f824f9e098b5058dfa3506a7ed3f62Sam Judd * @param <B> Some useful type that may be expensive to create (URL, file path, etc).
1578bad2aa32f824f9e098b5058dfa3506a7ed3f62Sam Judd * //TODO: fix this.
16425a2365cb61957bc52ae64ea7caa5f851c7bc72Sam Judd */
1778bad2aa32f824f9e098b5058dfa3506a7ed3f62Sam Juddpublic class ModelCache<A, B> {
18c5ba6fb229c79a6f90e9c430f11d02b43bfdc247Sam Judd    private static final int DEFAULT_SIZE = 250;
19425a2365cb61957bc52ae64ea7caa5f851c7bc72Sam Judd
2078bad2aa32f824f9e098b5058dfa3506a7ed3f62Sam Judd    private static class ModelKey<A> {
2178bad2aa32f824f9e098b5058dfa3506a7ed3f62Sam Judd        private static final Queue<ModelKey> KEY_QUEUE = new ArrayDeque<ModelKey>();
2278bad2aa32f824f9e098b5058dfa3506a7ed3f62Sam Judd
2378bad2aa32f824f9e098b5058dfa3506a7ed3f62Sam Judd        @SuppressWarnings("unchecked")
2478bad2aa32f824f9e098b5058dfa3506a7ed3f62Sam Judd        public static <A> ModelKey<A> get(A model, int width, int height) {
2578bad2aa32f824f9e098b5058dfa3506a7ed3f62Sam Judd            ModelKey<A> modelKey = KEY_QUEUE.poll();
2678bad2aa32f824f9e098b5058dfa3506a7ed3f62Sam Judd            if (modelKey == null) {
2778bad2aa32f824f9e098b5058dfa3506a7ed3f62Sam Judd                modelKey = new ModelKey<A>();
2878bad2aa32f824f9e098b5058dfa3506a7ed3f62Sam Judd            }
2978bad2aa32f824f9e098b5058dfa3506a7ed3f62Sam Judd
3078bad2aa32f824f9e098b5058dfa3506a7ed3f62Sam Judd            modelKey.init(model, width, height);
3178bad2aa32f824f9e098b5058dfa3506a7ed3f62Sam Judd            return modelKey;
3278bad2aa32f824f9e098b5058dfa3506a7ed3f62Sam Judd        }
3378bad2aa32f824f9e098b5058dfa3506a7ed3f62Sam Judd
3478bad2aa32f824f9e098b5058dfa3506a7ed3f62Sam Judd        private int height;
3578bad2aa32f824f9e098b5058dfa3506a7ed3f62Sam Judd        private int width;
3678bad2aa32f824f9e098b5058dfa3506a7ed3f62Sam Judd        private A model;
3778bad2aa32f824f9e098b5058dfa3506a7ed3f62Sam Judd
3878bad2aa32f824f9e098b5058dfa3506a7ed3f62Sam Judd        private ModelKey() {  }
39425a2365cb61957bc52ae64ea7caa5f851c7bc72Sam Judd
4078bad2aa32f824f9e098b5058dfa3506a7ed3f62Sam Judd        private void init(A model, int width, int height) {
4178bad2aa32f824f9e098b5058dfa3506a7ed3f62Sam Judd            this.model = model;
42425a2365cb61957bc52ae64ea7caa5f851c7bc72Sam Judd            this.width = width;
43425a2365cb61957bc52ae64ea7caa5f851c7bc72Sam Judd            this.height = height;
44425a2365cb61957bc52ae64ea7caa5f851c7bc72Sam Judd        }
45425a2365cb61957bc52ae64ea7caa5f851c7bc72Sam Judd
4678bad2aa32f824f9e098b5058dfa3506a7ed3f62Sam Judd        public void release() {
4778bad2aa32f824f9e098b5058dfa3506a7ed3f62Sam Judd            KEY_QUEUE.offer(this);
4878bad2aa32f824f9e098b5058dfa3506a7ed3f62Sam Judd        }
4978bad2aa32f824f9e098b5058dfa3506a7ed3f62Sam Judd
50425a2365cb61957bc52ae64ea7caa5f851c7bc72Sam Judd        @Override
51425a2365cb61957bc52ae64ea7caa5f851c7bc72Sam Judd        public boolean equals(Object o) {
52425a2365cb61957bc52ae64ea7caa5f851c7bc72Sam Judd            if (this == o) return true;
53425a2365cb61957bc52ae64ea7caa5f851c7bc72Sam Judd            if (o == null || getClass() != o.getClass()) return false;
54425a2365cb61957bc52ae64ea7caa5f851c7bc72Sam Judd
55425a2365cb61957bc52ae64ea7caa5f851c7bc72Sam Judd            ModelKey modelKey = (ModelKey) o;
56425a2365cb61957bc52ae64ea7caa5f851c7bc72Sam Judd
57425a2365cb61957bc52ae64ea7caa5f851c7bc72Sam Judd            if (height != modelKey.height) return false;
58425a2365cb61957bc52ae64ea7caa5f851c7bc72Sam Judd            if (width != modelKey.width) return false;
5978bad2aa32f824f9e098b5058dfa3506a7ed3f62Sam Judd            if (!model.equals(modelKey.model)) return false;
60425a2365cb61957bc52ae64ea7caa5f851c7bc72Sam Judd
61425a2365cb61957bc52ae64ea7caa5f851c7bc72Sam Judd            return true;
62425a2365cb61957bc52ae64ea7caa5f851c7bc72Sam Judd        }
63425a2365cb61957bc52ae64ea7caa5f851c7bc72Sam Judd
64425a2365cb61957bc52ae64ea7caa5f851c7bc72Sam Judd        @Override
65425a2365cb61957bc52ae64ea7caa5f851c7bc72Sam Judd        public int hashCode() {
66425a2365cb61957bc52ae64ea7caa5f851c7bc72Sam Judd            int result = height;
67425a2365cb61957bc52ae64ea7caa5f851c7bc72Sam Judd            result = 31 * result + width;
6878bad2aa32f824f9e098b5058dfa3506a7ed3f62Sam Judd            result = 31 * result + model.hashCode();
69425a2365cb61957bc52ae64ea7caa5f851c7bc72Sam Judd            return result;
70425a2365cb61957bc52ae64ea7caa5f851c7bc72Sam Judd        }
71425a2365cb61957bc52ae64ea7caa5f851c7bc72Sam Judd    }
72425a2365cb61957bc52ae64ea7caa5f851c7bc72Sam Judd
7378bad2aa32f824f9e098b5058dfa3506a7ed3f62Sam Judd    private final LruCache<ModelKey<A>, B> cache;
74c5ba6fb229c79a6f90e9c430f11d02b43bfdc247Sam Judd
759fc12334a7d14347cd6951d0653264b2597bd3a0Sam Judd    public ModelCache() {
76c5ba6fb229c79a6f90e9c430f11d02b43bfdc247Sam Judd        this(DEFAULT_SIZE);
77c5ba6fb229c79a6f90e9c430f11d02b43bfdc247Sam Judd    }
78c5ba6fb229c79a6f90e9c430f11d02b43bfdc247Sam Judd
799fc12334a7d14347cd6951d0653264b2597bd3a0Sam Judd    public ModelCache(int size) {
8078bad2aa32f824f9e098b5058dfa3506a7ed3f62Sam Judd        cache = new LruCache<ModelKey<A>, B>(size) {
8178bad2aa32f824f9e098b5058dfa3506a7ed3f62Sam Judd            @Override
8278bad2aa32f824f9e098b5058dfa3506a7ed3f62Sam Judd            protected void onItemRemoved(ModelKey<A> key, B item) {
8378bad2aa32f824f9e098b5058dfa3506a7ed3f62Sam Judd                key.release();
8478bad2aa32f824f9e098b5058dfa3506a7ed3f62Sam Judd            }
8578bad2aa32f824f9e098b5058dfa3506a7ed3f62Sam Judd        };
86c5ba6fb229c79a6f90e9c430f11d02b43bfdc247Sam Judd    }
87c5ba6fb229c79a6f90e9c430f11d02b43bfdc247Sam Judd
88425a2365cb61957bc52ae64ea7caa5f851c7bc72Sam Judd    /**
8978bad2aa32f824f9e098b5058dfa3506a7ed3f62Sam Judd     * Get a value.
90425a2365cb61957bc52ae64ea7caa5f851c7bc72Sam Judd     *
9178bad2aa32f824f9e098b5058dfa3506a7ed3f62Sam Judd     * @param model The model.
9278bad2aa32f824f9e098b5058dfa3506a7ed3f62Sam Judd     * @param width The width of the view the image is being loaded into.
9378bad2aa32f824f9e098b5058dfa3506a7ed3f62Sam Judd     * @param height The height of the view the image is being loaded into.
94425a2365cb61957bc52ae64ea7caa5f851c7bc72Sam Judd     *
9578bad2aa32f824f9e098b5058dfa3506a7ed3f62Sam Judd     * @return The cached result, or null.
96425a2365cb61957bc52ae64ea7caa5f851c7bc72Sam Judd     */
9778bad2aa32f824f9e098b5058dfa3506a7ed3f62Sam Judd    public B get(A model, int width, int height) {
9878bad2aa32f824f9e098b5058dfa3506a7ed3f62Sam Judd        ModelKey<A> key = ModelKey.get(model, width, height);
9978bad2aa32f824f9e098b5058dfa3506a7ed3f62Sam Judd        B result = cache.get(key);
10078bad2aa32f824f9e098b5058dfa3506a7ed3f62Sam Judd        key.release();
10178bad2aa32f824f9e098b5058dfa3506a7ed3f62Sam Judd        return result;
102425a2365cb61957bc52ae64ea7caa5f851c7bc72Sam Judd    }
103425a2365cb61957bc52ae64ea7caa5f851c7bc72Sam Judd
104425a2365cb61957bc52ae64ea7caa5f851c7bc72Sam Judd    /**
10578bad2aa32f824f9e098b5058dfa3506a7ed3f62Sam Judd     * Add a value.
106425a2365cb61957bc52ae64ea7caa5f851c7bc72Sam Judd     *
10778bad2aa32f824f9e098b5058dfa3506a7ed3f62Sam Judd     * @param model The model.
10878bad2aa32f824f9e098b5058dfa3506a7ed3f62Sam Judd     * @param width The width of the view the image is being loaded into.
10978bad2aa32f824f9e098b5058dfa3506a7ed3f62Sam Judd     * @param height The height of the view the image is being loaded into.
11078bad2aa32f824f9e098b5058dfa3506a7ed3f62Sam Judd     * @param value The value to store.
111425a2365cb61957bc52ae64ea7caa5f851c7bc72Sam Judd     */
11278bad2aa32f824f9e098b5058dfa3506a7ed3f62Sam Judd    public void put(A model, int width, int height, B value) {
11378bad2aa32f824f9e098b5058dfa3506a7ed3f62Sam Judd        ModelKey<A> key = ModelKey.get(model, width, height);
11478bad2aa32f824f9e098b5058dfa3506a7ed3f62Sam Judd        cache.put(key, value);
115425a2365cb61957bc52ae64ea7caa5f851c7bc72Sam Judd    }
116425a2365cb61957bc52ae64ea7caa5f851c7bc72Sam Judd}
117