Android之TypedArray 为什么需要调用recycle()
轉自:http://blog.csdn.net/Monicabg/article/details/45014327
在 Android 自定義 View 的時候,需要使用 TypedArray 來獲取 XML layout 中的屬性值,使用完之后,需要調用 recyle() 方法將 TypedArray 回收。
那么問題來了,這個TypedArray是個什么東西?為什么需要回收呢?TypedArray并沒有占用IO,線程,它僅僅是一個變量而已,為什么需要 recycle??
為了解開這個謎,首先去找官網的 Documentation,到找 TypedArray 方法,得到下面一個簡短的回答:
簡單翻譯下來,就是說:回收 TypedArray,用于后續調用時可復用之。當調用該方法后,不能再操作該變量。
同樣是一個簡潔的答復,但沒有解開我們心中的疑惑,這個TypedArray背后,到底隱藏著怎樣的秘密……
求之不得,輾轉反側,于是我們決定深入源碼,一探其究竟……
首先,是 TypedArray 的常規使用方法:
TypedArray array = context.getTheme().obtainStyledAttributes(attrs,R.styleable.PieChart,0,0); try {mShowText = array.getBoolean(R.styleable.PieChart_showText,false);mTextPos = array.getInteger(R.styleable.PieChart_labelPosition,0); }finally {array.recycle(); } 可見,TypedArray不是我們new出來的,而是調用了 obtainStyledAttributes 方法得到的對象,該方法實現如下:public TypedArray obtainStyledAttributes(AttributeSet set,int[] attrs, int defStyleAttr, int defStyleRes) {final int len = attrs.length;final TypedArray array = TypedArray.obtain(Resources.this, len);// other code .....return array; } 我們只關注當前待解決的問題,其他的代碼忽略不看。從上面的代碼片段得知,TypedArray也不是它實例化的,而是調用了TypedArray的一個靜態方法,得到一個實例,再做一些處理,最后返回這個實例。看到這里,我們似乎知道了什么,,,帶著猜測,我們進一步查看該靜態方法的內部實現:
/*** Container for an array of values that were retrieved with* {@link Resources.Theme#obtainStyledAttributes(AttributeSet, int[], int, int)}* or {@link Resources#obtainAttributes}. Be* sure to call {@link #recycle} when done with them.** The indices used to retrieve values from this structure correspond to* the positions of the attributes given to obtainStyledAttributes.*/ public class TypedArray {static TypedArray obtain(Resources res, int len) {final TypedArray attrs = res.mTypedArrayPool.acquire();if (attrs != null) {attrs.mLength = len;attrs.mRecycled = false;final int fullLen = len * AssetManager.STYLE_NUM_ENTRIES;if (attrs.mData.length >= fullLen) {return attrs;}attrs.mData = new int[fullLen];attrs.mIndices = new int[1 + len];return attrs;}return new TypedArray(res,new int[len*AssetManager.STYLE_NUM_ENTRIES],new int[1+len], len);}// Other members ...... }
仔細看一下這個方法的實現,我想大部分人都明了了,該類沒有公共的構造函數,只提供靜態方法獲取實例,顯然是一個典型的單例模式。在代碼片段的第 13 行,很清晰的表達了這個 array 是從一個 array pool的池中獲取的。
因此,我們得出結論:
程序在運行時維護了一個 TypedArray的池,程序調用時,會向該池中請求一個實例,用完之后,調用 recycle() 方法來釋放該實例,從而使其可被其他模塊復用。
那為什么要使用這種模式呢?答案也很簡單,TypedArray的使用場景之一,就是上述的自定義View,會隨著 Activity的每一次Create而Create,因此,需要系統頻繁的創建array,對內存和性能是一個不小的開銷,如果不使用池模式,每次都讓GC來回收,很可能就會造成OutOfMemory。
這就是使用池+單例模式的原因,這也就是為什么官方文檔一再的強調:使用完之后一定 recycle,recycle,recycle。
總結
以上是生活随笔為你收集整理的Android之TypedArray 为什么需要调用recycle()的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android之自定义属性,format
- 下一篇: Android之Activity的4种加