在Android开发过程中,使用到自定义属性的时候,经常到使用TypeArray,每次用完都要使用typeArray.recycle(),这句话的具体含义是什么?
先说答案:
获取typeArray时先会去TypeArray对象池中拿TypeArray对象,拿不到便会创建一个TypeArray对象,使用完再放回TypeArray对象池里,典型的享元模式,避免因频繁创建、销毁TypeArray对象造成内存抖动
再慢慢看源码:
- 先从TypeArray的获取,context.obtainStyledAttributes说起:
一步一步追源码:
context#obtainStyledAttributes
@NonNull
public final TypedArray obtainStyledAttributes(
@Nullable AttributeSet set, @NonNull @StyleableRes int[] attrs) {
return getTheme().obtainStyledAttributes(set, attrs, 0, 0);
}
getTheme的返回值是Resources的内部类
Resrouces#obtainStyledAttributes
@NonNull
public TypedArray obtainStyledAttributes(@Nullable AttributeSet set,
@NonNull @StyleableRes int[] attrs, @AttrRes int defStyleAttr,
@StyleRes int defStyleRes) {
return mThemeImpl.obtainStyledAttributes(this, set, attrs, defStyleAttr, defStyleRes);
}
Resources#obtainStyledAttributes
@NonNull
TypedArray obtainStyledAttributes(@NonNull Resources.Theme wrapper,
AttributeSet set,
@StyleableRes int[] attrs,
@AttrRes int defStyleAttr,
@StyleRes int defStyleRes) {
synchronized (mKey) {
final int len = attrs.length;
// 从TypedArray的obtain方法中获取,然后返回
final TypedArray array = TypedArray.obtain(wrapper.getResources(), len);
//xxxxxxx
return array;
}
}
咱们直接看最重要的一句,这里拿到了TypeArray对象 这里捋一下思路,所有的内容都是一路调用,最后将TypedArray.obtain中的typeArray返回
TypedArray#obtain
static TypedArray obtain(Resources res, int len) {
TypedArray attrs = res.mTypedArrayPool.acquire();
if (attrs == null) {
attrs = new TypedArray(res);
}
//xxxx
return attrs;
}
该方法中先从mTypeArrayPool中取,取不到,就自己创建一个,看名字更像是一个对象池 从res.mTypedArrayPool可以看出mTypeArrayPool是Resources类的成员变量 记住这里的acquire方法,下面有用
Resrouces#mTypedArrayPool
// Pool of TypedArrays targeted to this Resources object.
@UnsupportedAppUsage
final SynchronizedPool<TypedArray> mTypedArrayPool = new SynchronizedPool<>(5);
由注释证明了猜想,mTypeArrayPool确实是TypeArray对象池,查看下SynchronizedPool Pool#SynchronizedPool
public static class SynchronizedPool<T> extends SimplePool<T> {
private final Object mLock = new Object();
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);
}
}
}
最终的typeArray就是从这里(res.mTypedArrayPool.acquire()最终调用的这里)取的,看下父类SimplePool
public static class SimplePool<T> implements Pool<T> {
@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;
}
// mPoolSize是初始化大小5,mPool.length是当前池子的大小
@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;
}
}
直接从变量池里取的TypeArray对象。
那么typeArray.recycle(),调用的什么呢,直接点进去发现调用的是
TypeArray#recycle()
public void recycle() {
//xxx
//将改变放回对象池
mResources.mTypedArrayPool.release(this);
}
综上:获取typeArray时先会去对象池(大小为5)中拿TypeArray对象,拿不到便会创建一个TypeArray对象,使用完再放回对象池里,典型的享元模式,避免因频繁创建、销毁TypeArray对象造成内存抖动