blob: 55c0de0c724fe9ae6797af140bb5e84309a0b157 [file] [log] [blame]
package com.bumptech.glide.load.model;
import com.bumptech.glide.util.LruCache;
import com.bumptech.glide.util.Util;
import java.util.Queue;
/**
* A simple cache that can be used by {@link ModelLoader} and {@link ModelLoaderFactory} to cache some data for a given
* model, width and height. For a loader that takes a model and returns a url, the cache could be used to safely memoize
* url creation based on the width and height of the view.
*
* @param <A> Some Model type that implements {@link #equals} and {@link #hashCode}.
* @param <B> Some useful type that may be expensive to create (URL, file path, etc).
*/
public class ModelCache<A, B> {
private static final int DEFAULT_SIZE = 250;
private final LruCache<ModelKey<A>, B> cache;
public ModelCache() {
this(DEFAULT_SIZE);
}
public ModelCache(int size) {
cache = new LruCache<ModelKey<A>, B>(size) {
@Override
protected void onItemEvicted(ModelKey<A> key, B item) {
key.release();
}
};
}
/**
* Get a value.
*
* @param model The model.
* @param width The width in pixels of the view the image is being loaded into.
* @param height The height in pixels of the view the image is being loaded into.
*
* @return The cached result, or null.
*/
public B get(A model, int width, int height) {
ModelKey<A> key = ModelKey.get(model, width, height);
B result = cache.get(key);
key.release();
return result;
}
/**
* Add a value.
*
* @param model The model.
* @param width The width in pixels of the view the image is being loaded into.
* @param height The height in pixels of the view the image is being loaded into.
* @param value The value to store.
*/
public void put(A model, int width, int height, B value) {
ModelKey<A> key = ModelKey.get(model, width, height);
cache.put(key, value);
}
// Visible for testing.
static final class ModelKey<A> {
private static final Queue<ModelKey<?>> KEY_QUEUE = Util.createQueue(0);
private int height;
private int width;
private A model;
static <A> ModelKey<A> get(A model, int width, int height) {
@SuppressWarnings("unchecked")
ModelKey<A> modelKey = (ModelKey<A>) KEY_QUEUE.poll();
if (modelKey == null) {
modelKey = new ModelKey<A>();
}
modelKey.init(model, width, height);
return modelKey;
}
private ModelKey() { }
private void init(A model, int width, int height) {
this.model = model;
this.width = width;
this.height = height;
}
public void release() {
KEY_QUEUE.offer(this);
}
@Override
public boolean equals(Object o) {
if (o instanceof ModelKey) {
ModelKey other = (ModelKey) o;
return width == other.width && height == other.height && model.equals(other.model);
}
return false;
}
@Override
public int hashCode() {
int result = height;
result = 31 * result + width;
result = 31 * result + model.hashCode();
return result;
}
}
}