private final Map<String, Bitmap> cache = new HashMap<>()
private void setImage(ImageView iv, String name){
Bitmap b = cache.get(name);
if(b == null){
b = loadBitmap(name);
cache.put(name, b);
}
iv.setImageBitmap(b);
}
private final Map<Key, Bitmap> cache = new HashMap<>();
private void setImage(ImageView iv, String name, int width, int height){
Key key = new Key(name, width, height);
Bitmap b = cache.get(key);
if(b == null){
b = loadBitmap(name, width, height);
cache.put(key, b);
}
iv.setImageBitmap(b);
}
public class Key {
private final String name;
private final int width;
private final int heifht;
public Key(String name, int width, int heifht) {
this.name = name;
this.width = width;
this.heifht = heifht;
}
public String getName() {
return name;
}
public int getWidth() {
return width;
}
public int getHeifht() {
return heifht;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Key key = (Key) o;
if (width != key.width) {
return false;
}
if (heifht != key.heifht) {
return false;
}
return name != null ? name.equals(key.name) : key.name == null;
}
@Override
public int hashCode() {
int result = name != null ? name.hashCode() : 0;
final int prime = 31;
result = prime * result + width;
result = prime * result + heifht;
return result;
}
}
@Override
@NonNull
public Bitmap get(int width, int height, Bitmap.Config config) {
Bitmap result = getDirtyOrNull(width, height, config);
if (result != null) {
// Bitmaps in the pool contain random data that in some cases must be cleared for an image
// to be rendered correctly. we shouldn‘t force all consumers to independently erase the
// contents individually, so we do so here. See issue #131.
result.eraseColor(Color.TRANSPARENT);
} else {
result = createBitmap(width, height, config);
}
return result;
}
@Nullable
private synchronized Bitmap getDirtyOrNull(
int width, int height, @Nullable Bitmap.Config config) {
assertNotHardwareConfig(config);
// 对于非公共配置类型,配置为NULL,这可能导致转换以此处请求的配置方式天真地传入NULL。
final Bitmap result = strategy.get(width, height, config != null ? config : DEFAULT_CONFIG);
if (result == null) {
if (Log.isLoggable(TAG, Log.DEBUG)) {
Log.d(TAG, "Missing bitmap=" + strategy.logBitmap(width, height, config));
}
misses++;
} else {
hits++;
currentSize -= strategy.getSize(result);
tracker.remove(result);
normalize(result);
}
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "Get bitmap=" + strategy.logBitmap(width, height, config));
}
dump();
return result;
}
@Override
@Nullable
public Bitmap get(int width, int height, Bitmap.Config config) {
int size = Util.getBitmapByteSize(width, height, config);
Key bestKey = findBestKey(size, config);
//第一处代码
Bitmap result = groupedMap.get(bestKey);
if (result != null) {
decrementBitmapOfSize(bestKey.size, result);
result.reconfigure(width, height,
result.getConfig() != null ? result.getConfig() : Bitmap.Config.ARGB_8888);
}
return result;
}
private Key findBestKey(int size, Bitmap.Config config) {
//第二处代码
Key result = keyPool.get(size, config);
for (Bitmap.Config possibleConfig : getInConfigs(config)) {
NavigableMap<Integer, Integer> sizesForPossibleConfig = getSizesForConfig(possibleConfig);
Integer possibleSize = sizesForPossibleConfig.ceilingKey(size);
if (possibleSize != null && possibleSize <= size * MAX_SIZE_MULTIPLE) {
if (possibleSize != size
|| (possibleConfig == null ? config != null : !possibleConfig.equals(config))) {
keyPool.offer(result);
result = keyPool.get(possibleSize, possibleConfig);
}
break;
}
}
return result;
}
@VisibleForTesting
static class KeyPool extends BaseKeyPool<Key> {
Key get(int width, int height, Bitmap.Config config) {
Key result = get();
result.init(width, height, config);
return result;
}
@Override
protected Key create() {
return new Key(this);
}
}
@Nullable
public V get(K key) {
LinkedEntry<K, V> entry = keyToEntry.get(key);
if (entry == null) {
entry = new LinkedEntry<>(key);
keyToEntry.put(key, entry);
} else {
key.offer();
}
makeHead(entry);
return entry.removeLast();
}
/**
* <pre>
* @author yangchong
* blog : https://github.com/yangchong211
* time : 2017/05/30
* desc : 对象池抽象类
* revise: 具体使用方法请看:https://github.com/yangchong211/YCGallery
* </pre>
*/
public abstract class ObjectsPool<T> {
/*
* 防止频繁new对象产生内存抖动.
* 由于对象池最大长度限制,如果吞度量超过对象池容量,仍然会发生抖动.
* 此时需要增大对象池容量,但是会占用更多内存.
* <T> 对象池容纳的对象类型
*/
/**
* 对象池的最大容量
*/
private int mSize;
/**
* 对象池队列
*/
private Queue<T> mQueue;
/**
* 创建一个对象池
*
* @param size 对象池最大容量
*/
public ObjectsPool(int size) {
mSize = size;
mQueue = new LinkedList<>();
}
/**
* 获取一个空闲的对象
*
* 如果对象池为空,则对象池自己会new一个返回.
* 如果对象池内有对象,则取一个已存在的返回.
* take出来的对象用完要记得调用given归还.
* 如果不归还,让然会发生内存抖动,但不会引起泄漏.
*
* @return 可用的对象
*
* @see #given(Object)
*/
public T take() {
//如果池内为空就创建一个
if (mQueue.size() == 0) {
return newInstance();
} else {
//对象池里有就从顶端拿出来一个返回
return resetInstance(mQueue.poll());
}
}
/**
* 归还对象池内申请的对象
* 如果归还的对象数量超过对象池容量,那么归还的对象就会被丢弃
*
* @param obj 归还的对象
*
* @see #take()
*/
public void given(T obj) {
//如果对象池还有空位子就归还对象
if (obj != null && mQueue.size() < mSize) {
mQueue.offer(obj);
}
}
/**
* 实例化对象
*
* @return 创建的对象
*/
abstract protected T newInstance();
/**
* 重置对象
*
* 把对象数据清空到就像刚创建的一样.
*
* @param obj 需要被重置的对象
* @return 被重置之后的对象
*/
abstract protected T resetInstance(T obj);
}
public class MatrixPool extends ObjectsPool<Matrix>{
/**
* 矩阵对象池
*/
public MatrixPool(int size) {
super(size);
}
@Override
protected Matrix newInstance() {
return new Matrix();
}
@Override
protected Matrix resetInstance(Matrix obj) {
obj.reset();
return obj;
}
}
/**
* 矩阵对象池
*/
private static MatrixPool mMatrixPool = new MatrixPool(16);
/**
* 获取矩阵对象
*/
public static Matrix matrixTake() {
return mMatrixPool.take();
}
/**
* 获取某个矩阵的copy
*/
public static Matrix matrixTake(Matrix matrix) {
Matrix result = mMatrixPool.take();
if (matrix != null) {
result.set(matrix);
}
return result;
}
/**
* 归还矩阵对象
*/
public static void matrixGiven(Matrix matrix) {
mMatrixPool.given(matrix);
}
原文:https://www.cnblogs.com/yc211/p/10685476.html