1package com.bumptech.glide.load.engine.bitmap_recycle; 2 3import android.graphics.Bitmap; 4import android.os.Build; 5import android.util.Log; 6 7import static android.content.ComponentCallbacks2.TRIM_MEMORY_BACKGROUND; 8import static android.content.ComponentCallbacks2.TRIM_MEMORY_MODERATE; 9 10public class LruBitmapPool implements BitmapPool { 11 private static final String TAG = "LruBitmapPool"; 12 private final LruPoolStrategy strategy; 13 14 private final int initialMaxSize; 15 private int maxSize; 16 private int currentSize = 0; 17 private int hits; 18 private int misses; 19 private int puts; 20 private int evictions; 21 22 // Exposed for testing only. 23 LruBitmapPool(int maxSize, LruPoolStrategy strategy) { 24 this.initialMaxSize = maxSize; 25 this.maxSize = maxSize; 26 this.strategy = strategy; 27 } 28 29 public LruBitmapPool(int maxSize) { 30 initialMaxSize = maxSize; 31 this.maxSize = maxSize; 32 if (Build.VERSION.SDK_INT >= 19) { 33 strategy = new SizeStrategy(); 34 } else { 35 strategy = new AttributeStrategy(); 36 } 37 } 38 39 @Override 40 public void setSizeMultiplier(float sizeMultiplier) { 41 maxSize = Math.round(initialMaxSize * sizeMultiplier); 42 evict(); 43 } 44 45 @Override 46 public synchronized boolean put(Bitmap bitmap) { 47 if (!bitmap.isMutable() || strategy.getSize(bitmap) > maxSize) { 48 return false; 49 } 50 51 final int size = strategy.getSize(bitmap); 52 strategy.put(bitmap); 53 54 puts++; 55 currentSize += size; 56 57 if (Log.isLoggable(TAG, Log.DEBUG)) { 58 Log.d(TAG, "Put bitmap in pool=" + strategy.logBitmap(bitmap)); 59 } 60 dump(); 61 62 evict(); 63 return true; 64 } 65 66 private void evict() { 67 trimToSize(maxSize); 68 } 69 70 @Override 71 public synchronized Bitmap get(int width, int height, Bitmap.Config config) { 72 final Bitmap result = strategy.get(width, height, config); 73 if (result == null) { 74 if (Log.isLoggable(TAG, Log.DEBUG)) { 75 Log.d(TAG, "Missing bitmap=" + strategy.logBitmap(width, height, config)); 76 } 77 misses++; 78 } else { 79 hits++; 80 currentSize -= strategy.getSize(result); 81 } 82 if (Log.isLoggable(TAG, Log.DEBUG)) { 83 Log.d(TAG, "Get bitmap=" + strategy.logBitmap(width, height, config)); 84 } 85 dump(); 86 87 return result; 88 } 89 90 @Override 91 public void clearMemory() { 92 trimToSize(0); 93 } 94 95 @Override 96 public void trimMemory(int level) { 97 if (level >= TRIM_MEMORY_MODERATE) { 98 clearMemory(); 99 } else if (level >= TRIM_MEMORY_BACKGROUND) { 100 trimToSize(maxSize / 2); 101 } 102 } 103 104 private void trimToSize(int size) { 105 while (currentSize > size) { 106 final Bitmap removed = strategy.removeLast(); 107 currentSize -= strategy.getSize(removed); 108 removed.recycle(); 109 evictions++; 110 if (Log.isLoggable(TAG, Log.DEBUG)) { 111 Log.d(TAG, "Evicting bitmap=" + strategy.logBitmap(removed)); 112 } 113 dump(); 114 } 115 } 116 117 private void dump() { 118 if (Log.isLoggable(TAG, Log.VERBOSE)) { 119 Log.v(TAG, "Hits=" + hits + " misses=" + misses + " puts=" + puts + " evictions=" + evictions + " currentSize=" 120 + currentSize + " maxSize=" + maxSize + "\nStrategy=" + strategy); 121 } 122 } 123} 124