从Glide源码里面学习到的对象池知识

    对象池的概念是我在Glide源码里面第一次接触到的。它的作用是回收那些被释放的对象资源然后达到重用的目的。为什么要重用被释放的对象资源呢?因为创建对象是一个需要消耗内存的事情,重复大量的这些操作,会造成内存的抖动,这一点是每个开发者不愿意看到的。

   来看源码:

先看Engine类的waitForExistingOrStartNewJob方法,这个方法里面有一个创建对象DecodeJob的操作。它就用到了对象池的概念。

1
2
3
4
// Engine
private <R> LoadStatus waitForExistingOrStartNewJob(......) {
DecodeJob<R> decodeJob = decodeJobFactory.build(......);
}

来直接看decodeJobFactory.build方法:

1
2
3
4
5
// Engine.DecodeJobFactory
DecodeJob<R> build(.......) {
DecodeJob<R> result = pool.acquire();
return result;
}

好重点来了:pool对象。从名字就能知道这是一个池子,是什么池子?当然是对象池子。

1
2
3
4
5
6
7
8
9
final Pools.Pool<EngineJob<?>> pool =
FactoryPools.threadSafe(
JOB_POOL_SIZE(150),
new FactoryPools.Factory<EngineJob<?>>() {
@Override
public EngineJob<?> create() {
return new EngineJob<>(....);
}
});

看下FactoryPools代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// FactoryPools
public static <T extends Poolable> Pool<T> threadSafe(int size, @NonNull Factory<T> factory) {
return build(new SynchronizedPool<T>(size), factory);
}
@NonNull
private static <T extends Poolable> Pool<T> build(
@NonNull Pool<T> pool, @NonNull Factory<T> factory) {
return build(pool, factory, FactoryPools.<T>emptyResetter());
}

@NonNull
private static <T> Pool<T> build(
@NonNull Pool<T> pool, @NonNull Factory<T> factory, @NonNull Resetter<T> resetter) {
return new FactoryPool<>(pool, factory, resetter);
}

这里就是它设计精妙的地方,创建对象的操作用一个接口回调出来:

1
2
3
public interface Factory<T> {
T create();
}

现在知道了pool对象的由来,它就是FactoryPool

继续回到代码pool.acquire(),看FactoryPoolacquire

1
2
3
4
5
6
7
8
9
10
// FactoryPools
public T acquire() {
// 先从SynchronizedPool这里取
T result = pool.acquire();
if (result == null) {
// 取不到在创建对象
result = factory.create();
}
return result;
}

可以看到在acquire里面有调用了一个pool:这个pool其实是SynchronizedPool,在创建FactoryPools的时候创建的。这里为啥会出现两个Pool。这个FactoryPools是从池子里做取创建得操作。SynchronizedPool这个池子做的是存删得操作。

1
2
3
4
5
6
7
8
9
10
11
12
//SynchronizedPool
//做取得操作,去完就从自己得队列里面删掉
public T acquire() {
if (mPoolSize > 0) {
final int lastPooledIndex = mPoolSize - 1;
T instance = (T) mPool[lastPooledIndex];
mPool[lastPooledIndex] = null;
mPoolSize--;
return instance;
}
return null;
}

总结:

    它的逻辑就是,我想获取对象的时候。FactoryPools执行acquire方法,然后这个方法调用SynchronizedPool里面的acquire方法从HashMap里面取。如果没取到对象那么FactoryPools就执行create创建对象。如果在SynchronizedPool里面取到了,就从它的HashMap里面取出这个对象,然后把HashMap的最后一个项删掉。到这里取得操作执行完了。现在执行释放得操作。当某个对象要被释放了,不用了,那么就执行FactoryPoolsrelease方法,这个方法会调用SynchronizedPoolrelease操作,将这个被释放的对象缓存起来,保存在HaseMap里面。好了释放的操作完成了。当然缓存的大小肯定是有限制的,不能不限缓存。

    如果在以后的项目里面你有出现会频繁创建对象的操作的时候,可以使用Glide的这部分知识,更高效的重用已经创建过的对象。代码可以直接抄:FactoryPoolsSynchronizedPool可以直接用。