对象池,我们知道是存了对象的,将来可以复用,这样避免频繁地创建和回收常用对象,造成内存抖动,降低app的性能。
对于普通的对象来说,其本身占用内存很小,同时在放到对象池的时候,会对对象重置的,所以对象池不会关心对象个体的内存大小,只关心对象的数量。基本上有两种实现方案,数组和单链表,Android官方都有实现使用,Pools采用了数组,大小可以自己指定,Message采用了单链表,可以存50个message对象,如果对象池中对象满了,再放直接抛弃就行。具体可以看Glide(Android)之普通对象池
还有一种对象池,存的就不是普通对象了,是为了专门复用其内存的,比如Bitmap,所以此时的对象池关心的是内存大小,不再是对象个数。对于Bitmap地复用来说,比较复杂,不是说从Bitmap对象池中取出一个Bitmap就能复用。具体可以看Android之 Bitmap
Android官方给里例子是把复用的bitmap方法一个Set中,
(1)这样从Set取bitmap的时候就得遍历了,然后获取满足的bitmap(4.4之前和之后复用方式是不一样的),
(2)而且,对对象池大小没有管理。
(3)获取到可以复用的bitmap之后,需要从set中移除
在Glide进行了改进,采用了Lru 的map来存bitmap,这样通过key查找效率高,同时,还管理了对象池大小,满了抛弃不常用的,其实这样是合理的,因为不常用的没有必要放对象池,要不然就失去了对象池的意义。同时,还采用了一个map来记录,Config和Size,的个数count,如果获取到可以复用的bitmap,只需要count减1就可以,不需要真正把Bitmap中对象池拿掉。
下面这篇文章基本讲的很完整
Glide4.8源码拆解(五)BitmapPool从入门到放弃
说完了LruBitmapPool对象池,我们得说一些Glide中是怎么用的
首先复用Bitmap,要想复用肯定是找到合适的Bitmap,付给BitmapFactory.Options 的inBitmap,这个是在Downsampler中做的
@TargetApi(Build.VERSION_CODES.O)
private static void setInBitmap(
BitmapFactory.Options options, BitmapPool bitmapPool, int width, int height) {
@Nullable Bitmap.Config expectedConfig = null;
// Avoid short circuiting, it appears to break on some devices.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
if (options.inPreferredConfig == Config.HARDWARE) {
return;
}
// On API 26 outConfig may be null for some images even if the image is valid, can be decoded
// and outWidth/outHeight/outColorSpace are populated (see b/71513049).
expectedConfig = options.outConfig;
}
if (expectedConfig == null) {
// We're going to guess that BitmapFactory will return us the config we're requesting. This
// isn't always the case, even though our guesses tend to be conservative and prefer configs
// of larger sizes so that the Bitmap will fit our image anyway. If we're wrong here and the
// config we choose is too small, our initial decode will fail, but we will retry with no
// inBitmap which will succeed so if we're wrong here, we're less efficient but still correct.
expectedConfig = options.inPreferredConfig;
}
// BitmapFactory will clear out the Bitmap before writing to it, so getDirty is safe.
options.inBitmap = bitmapPool.getDirty(width, height, expectedConfig);
}
DownSampler里面也是很重要的一块内容,这篇文章不错,以后有机会看Glide4.8源码拆解(四)Bitmap解析之"下采样"浅析
回收是在不用的时候,有很多种情况
(1)ActiveResources中移除的时候,如果设置不放到MemoryCache中,最终会到BitmapPool里
(2)MemoryCache淘汰出来的,也会回收到Bitmap里面。
(3)其它出错的时候