有用链接
- 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