Android关于Typedarray的使用

本文详细介绍了如何使用TypedArray为自定义View添加属性,并解释了TypedArray的工作原理及其在Android开发中的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、Typedarray干什么用的

我们在写界面布局的xml时,经常要设置组件的属性,比如常用的

android:id="@+id/id_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
复制代码

而假如我们需要对自定义的view、viewgroup等等添加自定义的属性呢?就是需要typedarray了。这次我们的例子是给自定义的view添加属性。

二、怎么用Typedarray

1.准备一个自定义的view

code警告

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。

还有其他可选的类型有:

reference 表示引用,参考某一资源ID
string 表示字符串
color 表示颜色值
dimension 表示尺寸值
boolean 表示布尔值
integer 表示整型值
float 表示浮点值
fraction 表示百分数
enum 表示枚举值
flag 表示位运算

3.主角出现:用typedarray获取xml中的属性

通过Contex的obtainStyledAttributes方法创建typedarray,然后用getXXX来获取对应的属性。

show me the code

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中使用了

@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

结果图:

三、最后一点思考

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开发的初学者,如果我有错误的地方或者不足的话欢迎大家指正。希望与大家一同进步

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值