BitmapPool
接口定义
public interface BitmapPool {
long getMaxSize();
void setSizeMultiplier(float sizeMultiplier);
Bitmap get(int width, int height, Bitmap.Config config);
Bitmap getDirty(int width, int height, Bitmap.Config config);
void clearMemory();
void trimMemory(int level);
}
Bitmap缓存池的接口,作用是复用Bitmap对象内存,当一个Bitmap不再被使用时,Glide会把Bitmap占用的内存放到缓存池中,当有相同参数的Bitmap需要创建时,优先从缓存池中请求内存,避免频繁分配内存。与Handler的Message对象复用思路一致。默认实现是LruBitmapPool,采用LRU原则控制缓存大小。
put
Glide中放入缓存池的时机,主要在两个地方:
1、bitmap 被回收(recycle)
2、bitmap作为临时变量,暂时为生成其他bitmap存储数据
被回收容易理解,put调用通常位于recycle方法中:
public class BitmapDrawableResource{
@Override
public void recycle() {
bitmapPool.put(drawable.getBitmap());
}
}
public class BitmapResource{
@Override
public void recycle() {
bitmapPool.put(drawable.getBitmap());
}
}
final class BitmapPreFillRunner implements Runnable {
boolean allocate() {
bitmapPool.put(bitmap);
}
}
作为中间变量存储数据是指,当Glide获取了图片的原始数据,但是图片需要处理后,才能被使用,所以put调用常常位于数据解析后,但是被应用前的位置:
public final class Downsampler {
//从inputStream解析数据
private Bitmap decodeFromWrappedStreams(...){
bitmapPool.put(downsampled);
}
private static Bitmap decodeStream(...){
bitmapPool.put(options.inBitmap);
}
}
public class StreamBitmapDecoder{
//从inputStream解析数据
public void onDecodeComplete(...){
bitmapPool.put(downsampled);
}
}
public final class TransformationUtils {
//对图片进行变换
public static Bitmap circleCrop(...){
pool.put(toTransform);
}
//对图片进行变换
public static Bitmap roundedCorners(...){
pool.put(toTransform);
}
}
get
get方法应用的地方集中在图片变换的步骤中:从缓存池获取bitmap内存,把最后需要使用的图片数据,放到bitmap中。
public final class TransformationUtils {
private static Bitmap drawToBitmap(){
Bitmap result = bitmapPool.get(targetWidth, targetHeight, Bitmap.Config.ARGB_8888);
}
public static Bitmap circleCrop(...){
Bitmap result = pool.get(width, height, getNonNullConfig(inBitmap));
}
public static Bitmap centerCrop(...){
Bitmap result = pool.get(width, height, getNonNullConfig(inBitmap));
}
public static Bitmap rotateImageExif(...){
Bitmap result = pool.get(width, height, getNonNullConfig(inBitmap));
}
public static Bitmap fitCenter(...){
Bitmap result = pool.get(width, height, getNonNullConfig(inBitmap));
}
public static Bitmap roundedCorners(...){
pool.put(toTransform);
}
}
ArrayPool
理解了BitmapPool,其实ArrayPool也差不多。Glide需要处理很多图片的数据,不可避免的要从InputStream中读取数据,这时候就要用到byte数组(byte[]),ArrayPool作用就是缓存byte数组,避免频繁创建对象。
最后
理解源码不是最终目的,纸上得来终觉浅,绝知此事要躬行,学习优秀的代码,最重要的是掌握其中的思想,并应用到自己的项目中。
Glide的开发者们在一开始,一定没有想到内存方面的优化,而是通过性能分析,定位到这里,并提出这样一个解决方案。
因此,必须掌握如何分析app内存:
Android性能优化:使用Profiler进行内存优化