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开发的初学者,若是我有错误的地方或者不足的话欢迎你们指正。但愿与你们一同进步

相关文章
相关标签/搜索