Testing TypedArray recycle() does not throw RuntimeException

470 Views Asked by At

I tested TypedArray recycle with this code, expecting to get a runtime exception based on the documentation, but I did not get one.

recycle

added in API level 1
void recycle () Recycles the TypedArray, to be re-used by a later caller. After calling this function you must not ever touch the typed array again.

Throws RuntimeException if the TypedArray has already been recycled.

    public TimePickerPreference(Context context, AttributeSet attrs) {
        super(context, attrs);
        TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.TimePickerPreference, 0, 0);
        initTimePickerPreference(a);
        a.recycle();
    }
    protected void initTimePickerPreference(TypedArray a) {

        if (a != null)
            try {
                setTitle(a.getString(R.styleable.TimePickerPreference_android_title));
                mSummary = a.getString(R.styleable.TimePickerPreference_android_summary);
                mDefaultValue = a.getString(R.styleable.TimePickerPreference_android_defaultValue);
            } finally {
                a.recycle();
            }

    ...
    }

I traced the code with the Android Studio debugger and it went through both a.recycle() calls, while in variables pane a was not made null

The reason I made this test is because I was not 100% sure if it was OK to call a.recycle() in a different scope from where a was created.

I went further and duplicated the recycle call

    public TimePickerPreference(Context context, AttributeSet attrs) {
        super(context, attrs);
        TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.TimePickerPreference, 0, 0);
        initTimePickerPreference(a);
        a.recycle();
        a.recycle();
    }
    protected void initTimePickerPreference(TypedArray a) {

        if (a != null)
            try {
                setTitle(a.getString(R.styleable.TimePickerPreference_android_title));
                mSummary = a.getString(R.styleable.TimePickerPreference_android_summary);
                mDefaultValue = a.getString(R.styleable.TimePickerPreference_android_defaultValue);
            } finally {
                a.recycle();
                a.recycle();
            }

    ...
    }

Still no RunTimeException.

Is this a bug?
I ran it on AVD emulated device with Android IceCreamSandwich version (API 15).

1

There are 1 best solutions below

3
On BEST ANSWER

Here's the implementation of TypedArray#recycle() for API 15:

 public void recycle() {
     synchronized (mResources.mTmpValue) {
         TypedArray cached = mResources.mCachedStyledAttributes;
         if (cached == null || cached.mData.length < mData.length) {
             mXml = null;
             mResources.mCachedStyledAttributes = this;
         }
     }
 }

Here's the implementation for API 25:

public void recycle() {
    if (mRecycled) {
        throw new RuntimeException(toString() + " recycled twice!");
    }
    mRecycled = true;
    // These may have been set by the client.
    mXml = null;
    mTheme = null;
    mAssets = null;
    mResources.mTypedArrayPool.release(this);
}

Obviously, docs state the implementation of the latest API, and you are running your app with API 15.