【Glide 】框架在内存使用方面的优化

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进行内存优化

猜你喜欢

转载自blog.csdn.net/qq_23049111/article/details/125305714