使用对象池Pools,优化频繁创建和销毁的代码
2017-02-16 本文已影响409人
InKenKa
前言
在阅读Glide源码时,发现Glide大量使用对象池Pools来对频繁需要创建和销毁的代码进行优化。
比如Glide中,每个图片请求任务,都需要用到 EngineJob 、DecodeJob类。若每次都需要重新new这些类,并不是很合适。而且在大量图片请求时,频繁创建和销毁这些类,可能会导致内存抖动,影响性能。
Glide使用对象池的机制,对这种频繁需要创建和销毁的对象保存在一个对象池中。每次用到该对象时,就取对象池空闲的对象,并对它进行初始化操作,从而提高框架的性能。
代码介绍
1. 用到的类
android.support.v4.util.Pool
2. Pool接口类
acquire(): 从对象池请求对象的函数:
release(): 释放对象回对象池的函数
public static interface Pool<T> {
public T acquire();
public boolean release(T instance);
}
3. Android官方对象池的简单实现:SimplePool,也是用得最多的实现
原理:使用了“懒加载”的思想。当SimplePool初始化时,不会生成N个T类型的对象存放在对象池中。而是当每次外部调用release()时,才把释放的T类型对象存放在对象池中。要先放入,才能取出来。
public static class SimplePool<T> implements Pool<T> {
private final Object[] mPool;
private int mPoolSize;
public SimplePool(int maxPoolSize) {
if (maxPoolSize <= 0) {
throw new IllegalArgumentException("The max pool size must be > 0");
}
mPool = new Object[maxPoolSize];
}
@Override
@SuppressWarnings("unchecked")
public T acquire() {
if (mPoolSize > 0) {
final int lastPooledIndex = mPoolSize - 1;
T instance = (T) mPool[lastPooledIndex];
mPool[lastPooledIndex] = null;
mPoolSize--;
return instance;
}
return null;
}
@Override
public boolean release(T instance) {
if (isInPool(instance)) {
throw new IllegalStateException("Already in the pool!");
}
if (mPoolSize < mPool.length) {
mPool[mPoolSize] = instance;
mPoolSize++;
return true;
}
return false;
}
private boolean isInPool(T instance) {
for (int i = 0; i < mPoolSize; i++) {
if (mPool[i] == instance) {
return true;
}
}
return false;
}
}
4. 对SynchronizedPool的简单封装
由于对象池设计是要先放入,才能取出来。所以当没有放入对象时,调用acquire(),返回都是null,所以可以对 对象池进行以下封装,方便其使用:
public class MyPooledClass {
private static final SynchronizedPool<MyPooledClass> sPool =
new SynchronizedPool<MyPooledClass>(10);
public static MyPooledClass obtain() {
MyPooledClass instance = sPool.acquire();
return (instance != null) ? instance : new MyPooledClass();
}
public void recycle() {
sPool.release(this);
}
}