Android關於Typedarray的使用

1、Typedarray幹什麼用的

咱們在寫界面佈局的xml時,常常要設置組件的屬性,好比經常使用的java

android:id="@+id/id_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
複製代碼

而假如咱們須要對自定義的view、viewgroup等等添加自定義的屬性呢?就是須要typedarray了。此次咱們的例子是給自定義的view添加屬性。android

2、怎麼用Typedarray

1.準備一個自定義的view

code警告canvas

public class ViewWithAttrs extends View {
    public ViewWithAttrs(Context context, AttributeSet attrs){
        super(context, attrs);
    }
}
複製代碼

2.準備(新建)一個arrts.xml

這個xml就是定義屬性的地方,咱們打開以後添加這個

<resources>
    <declare-styleable name="ViewWithAttrs">
        <attr name="paint_color" format="color"/>
    </declare-styleable>
</resources>
複製代碼

注意第二行的name="ViewWithAttrs",name就是你要添加屬性的組件,必定要和view名字相同。緩存

而後就是添加咱們想要的屬性了,這裏我添加了一條屬性,屬性名是"paint_color",這個是本身定義的,屬性類型是:color。app

還有其餘可選的類型有:ide

reference 表示引用,參考某一資源ID
string 表示字符串
color 表示顏色值
dimension 表示尺寸值
boolean 表示布爾值
integer 表示整型值
float 表示浮點值
fraction 表示百分數
enum 表示枚舉值
flag 表示位運算佈局

3.主角出現:用typedarray獲取xml中的屬性

經過Contex的obtainStyledAttributes方法建立typedarray,而後用getXXX來獲取對應的屬性。測試

show me the codeui

public class ViewWithAttrs extends View {

    private Paint mPaint;

    public ViewWithAttrs(Context context, AttributeSet attrs){
        super(context, attrs);
        mPaint = new Paint();
        mPaint.setStyle(Paint.Style.STROKE);
        mPaint.setAntiAlias(true);
        //首先經過obtainStyledAttributes方法獲取typedarray
        TypedArray typedArray = context.obtainStyledAttributes(attrs,R.styleable.ViewWithAttrs);
        //使用typedarray獲取對應的屬性
        int paintColor = typedArray.getColor(R.styleable.ViewWithAttrs_paint_color, Color.BLACK);
        //最後的Color.BLACK是沒獲取到時的默認值
        mPaint.setColor(paintColor);
        typedArray.recycle();//不要忘記回收!
    }
}
複製代碼

這樣咱們獲取到了咱們想要的屬性,能夠在這個View中使用了idea

@Override
protected void onDraw(Canvas canvas){
    super.onDraw(canvas);
    canvas.drawCircle(200,200,50,mPaint);
}
複製代碼

4.等等,咱們還沒設置好屬性

在MainActivity的佈局文件activity_main.xml中添加咱們的view並設置好屬性

<com.idealcountry.test.ViewWithAttrs
        android:id="@+id/id_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:paint_color="@color/blue"/>
複製代碼

這樣咱們就能在代碼中獲取xml設置好的paint_color了。//這裏我在color.xml中註冊了一個顏色:color/blue

結果圖:

3、最後一點思考

AttributeSet的問題

小德我在寫自定義的View時,剛開始定義了一個類的屬性用來保存從AttributeSet獲取的typedarray,可是手滑了把獲取typedarray寫到了onDraw()方法裏了,測試的時候後發現沒有成功獲取到xml中定義的屬性,經過debug這才知道在onDraw方法中拿到的值是空的,採用了默認值。可是這是爲何呢?

通過查找到layoutInflater這個類才清楚,大概意思就是AttributeSet並非每一個View都分配一個,而是有相似於緩存同樣的機制,你們是共用的(大概能夠這麼理解),因此到ondraw就有可能獲取到了不是咱們須要的AttributeSet了。

typedarray回收?不存在的

爲何必定要強調回收呢?這東西又不是佔了線程,我就不回收能怎麼樣?(其實不回收的話AS也會一直煩你,說你沒有回收)

爲了弄清楚,咱們須要進入源碼來看一看。幾回goto declaration,咱們最終在Typedarray.java中找到了,注意這個靜態方法裏的第一句。

static TypedArray obtain(Resources res, int len) {
        TypedArray attrs = res.mTypedArrayPool.acquire();
        if (attrs == null) {
            attrs = new TypedArray(res);
        }

        attrs.mRecycled = false;
        // Reset the assets, which may have changed due to configuration changes
        // or further resource loading.
        attrs.mAssets = res.getAssets();
        attrs.mMetrics = res.getDisplayMetrics();
        attrs.resize(len);
        return attrs;
    }
複製代碼

並且這個類的構造方法隱藏了,是protected的,很明顯的一個單例模式。

/** @hide */
    protected TypedArray(Resources resources) {
        mResources = resources;
        mMetrics = mResources.getDisplayMetrics();
        mAssets = mResources.getAssets();
    }
複製代碼

這樣就清楚了,typedarray是咱們在靜態方法Typedarray.obtain中獲取的,是從一個Typedarray池中取出來。不難理解,咱們在view中使用typedarray,view會隨着activity的create而create,這樣咱們總不能每次都new一個typedarray出來,因此採用了使用typedarray池來管理。這也就是官方一直強調,用完後要衝水,啊不是,用完後必定要回收。

O了個快速排序K

//做爲Android開發的初學者,若是我有錯誤的地方或者不足的話歡迎你們指正。但願與你們一同進步

相關文章
相關標籤/搜索