该文章属于《Android Handler机制之》系列文章,若是想了解更多,请点击 《Android Handler机制之总目录》android
在上篇文章《Android Handler机制之Message及Message回收机制 》咱们讲解了Message中所携带的信息及消息池中的实现方式。其中咱们已经了解了Message中消息池是以链表的形式来完成。在完成了上篇文章后,我就一直想在Java或Android中是否已经为咱们提供了一种对象池来帮助咱们来实现缓存对象的实现呢。果然在Android中的android.support.v4.util下的Pools类就为咱们提供了SimplePool、SynchronizedPool来建立对象池。下面我就对该包下的类进行讲解。数组
在android.support.v4.util包下的Pools类中,分别声明了Pool接口,SimplePool实现类与SynchronizedPool实现类,其中具体的UML关系以下图所示: 缓存
在讨论了具体的UML关系后,如今咱们来看看SimplePool的代码实现,具体代码以下图所示:安全
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--;//当前对象池中对象个数减1
return instance;
}
return null;
}
//回收当前对象到对象池中,
@Override
public boolean release(@NonNull 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(@NonNull T instance) {
for (int i = 0; i < mPoolSize; i++) {
if (mPool[i] == instance) {
return true;
}
}
return false;
}
}
复制代码
对于SimplePool的代码其实很好理解,其对象池是以数组的方式来实现的。其中对象池的最大容量是经过用户手动设定。从对象池中获取数据是经过acquire方法。回收当前对象到对象池中是经过release方法。关于这两个方法的详细流程会在下文具体介绍。bash
在acquire方法中,会从对象池中取出对象。具体列子以下图所示: 多线程
总结:acquire()方法总会取当前对象池中存储的最后一个数据。若是有则返回。同时将该位置置为null。反之返回为null。less
在release方法中,会将对象缓存到对象池中。若是当前对象已经存在,会抛出异常。反之则存储。具体列子以下图所示: ide
总结:release( T instance)方法,总会将须要回收的对象存入当前对象池中存储的最后一个数据的下一个位置。若是当前回收的对象已经存在会抛出异常。反之则成功。post
在前面的文章中咱们介绍了SimplePool的存取数据的主要实现。细心的小伙伴确定都已经发现了。在多线程的状况下,若是使用SimplePool确定是会出现问题的。可是Google已经为咱们考虑到了,为咱们提供了线程安全的对象池SynchronizedPool,下面咱们就来看看SynchronizedPool的具体实现。具体代码以下ui
public static class SynchronizedPool<T> extends SimplePool<T> {
private final Object mLock = new Object();
/**
* Creates a new instance.
*
* @param maxPoolSize The max pool size.
*
* @throws IllegalArgumentException If the max pool size is less than zero.
*/
public SynchronizedPool(int maxPoolSize) {
super(maxPoolSize);
}
@Override
public T acquire() {
synchronized (mLock) {
return super.acquire();
}
}
@Override
public boolean release(@NonNull T element) {
synchronized (mLock) {
return super.release(element);
}
}
}
复制代码
SynchronizedPool的代码理解起来也一样很是简单,直接继承SimplePool。并重写了SimplePool的两个方法。并为其加上了锁,保证了多线程状况下使用的安全性。
上面咱们讨论了两种不一样的对象池的实现,下面咱们来看看对于这两种对象池的使用。这里就使用官方的SynchronizedPool的使用例子(这里对SimplePool的使用也是通用的,根据是否须要多线程操做来选择不一样的对象池)。
public class MyPooledClass {
//声明对象池的大小
private static final SynchronizedPool<MyPooledClass> sPool =
new SynchronizedPool<MyPooledClass>(10);
//从对象池中获取数据,若是为null,则建立
public static MyPooledClass obtain() {
MyPooledClass instance = sPool.acquire();
return (instance != null) ? instance : new MyPooledClass();
}
//回收对象到对象池中。固然你也能够清除对象的状态
public void recycle() {
// 清除对象的状态,若是你本身须要的话,
sPool.release(this);
}
}
复制代码