有用鏈接
- BitmapOptions參數詳解:https://www.jianshu.com/p/c545f2a6cafc (bitmap的最優使用)
- 內存複用的實現原理:https://www.jianshu.com/p/eadb0ef271b0
- 裏面的demo非常值得看
Bitmap複用的原理
(1)將需要回收的Bitmap保存在List
Glide實現
類圖
圖片來源:https://juejin.im/entry/59004a0c61ff4b0066819a15
實現原理簡述:
(1)put(Bitmap)過程
- 根據Strategy對Bitmap構建Key,不同的Strategy,Key生成方式不同
- SizeStrategy:size相同的Bitmap,Key相同
- SizeConfigStrategy:size和config相同的Bitmap,Key相同
- AttributeStrategy:width,height,config相同的Bitmap,Key相同
- 然後調用GroupedLinkedMap.put(Key,Bitmap)將BitMap緩存到GroupedLinkedMap之中。
- 由於不同Bitmap在生成Key的時候可能會有衝突,Glide解決衝突的方式是實現GroupedLinkedMap,將Key值相同的Bitmap保存在一個ArrayList裏面。
重點類說明
其他的類都比較好理解,針對其中的幾個比較特殊的類做簡單的解釋
GroupedLinkedMap
(1)作用:按照Key(在FillStrategy裏面定義,比如Bitmap的size),存儲Value(Bitmap)。不同於傳統的HashMap,對於Key相同的Entry, 其保存在一個ArrayList裏面,而不是採用覆蓋的形式。
(2)實現機制:
GroupedLinkedMap的結構:
class GroupedLinkedMap<K extends Poolable, V> {
private final LinkedEntry<K, V> head = new LinkedEntry<>();
private final Map<K, LinkedEntry<K, V>> keyToEntry = new HashMap<>();
}
LinkedEntry的結構:
private static class LinkedEntry<K, V> {
@Synthetic
final K key;
// Value是一個List<V>
private List<V> values;
LinkedEntry<K, V> next;
}
Strategy
Get方法
Bitmap get(int width, int height, Bitmap.Config config)
計算需要的Bitmap的大小方法
public static int getBitmapByteSize(int width, int height, @Nullable Bitmap.Config config) {
return width * height * getBytesPerPixel(config);
}
private static int getBytesPerPixel(@Nullable Bitmap.Config config) {
// A bitmap by decoding a GIF has null "config" in certain environments.
if (config == null) {
config = Bitmap.Config.ARGB_8888;
}
int bytesPerPixel;
switch (config) {
case ALPHA_8:
bytesPerPixel = 1;
break;
case RGB_565:
case ARGB_4444:
bytesPerPixel = 2;
break;
case RGBA_F16:
bytesPerPixel = 8;
break;
case ARGB_8888:
default:
bytesPerPixel = 4;
break;
}
return bytesPerPixel;
}
SizeStrategy
- 計算出需要的Bitmap的size
- 選擇Bitmap的條件:(CacheBitmap.size>=size)
- 選擇符合條件的最小值
SizeConfigStrategy
- 計算出需要的Bitmap的size
- 選擇Bitmap的條件 :CacheBitmap.config==config&&CacheBitmap.size>=size
- 選擇符合條件的最小值
AttributeStrategy
- 選擇Bitmap的條件:CacheBimap.width==width && CacheBitmap.height==height&& CacheBitmap.config==config
- 選擇符合條件的Bitmap