• Android 中 declarestyleable 和 style 的不同


    最近修改一个python写的小工具,用作移除Android项目中没用到的资源如string, color等等。在做的过程中,style和styleable一直困扰不清,后面查了一下stackoverflow http://stackoverflow.com/questions/4585808/difference-between-declare-styleable-and-style ,总结一下这个问题。


    一、style的作用

    首先需要了解style的作用是什么!Android developer http://developer.android.com/intl/zh-CN/guide/topics/ui/themes.html 给出了一个例子我觉得很说明问题。

    如果我们需要定义很多个这样的TextView:

    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:textColor="#00FF00"
        android:typeface="monospace"
        android:text="@string/hello" />

    为了便于修改,我们可以修改成这样:

    <TextView
        style="@style/CodeFont"
        android:text="@string/hello" />
    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <style name="CodeFont" parent="@android:style/TextAppearance.Medium">
            <item name="android:layout_width">fill_parent</item>
            <item name="android:layout_height">wrap_content</item>
            <item name="android:textColor">#00FF00</item>
            <item name="android:typeface">monospace</item>
        </style>
    </resources>

    这样,我们只要采用CodeFont的style的view都会有一样的外观,而且很容易修改。所以,style可以理解成自定义外观,重复利用代码的作用。

    至于styleable,我们注意到它是在attrs.xml中定义的,所以我们可以想象,它可能是用于定义attr在style里面用。具体的区别马上就讲。

    二、declare-styleable 和 style 的区别

    为什么在attrs.xml里面会有styleable的定义呢?

    我们注意到上文中的CodeFont的定义,有没有发现item里面的name都是android开头?因为这些属性都是在android中预先设定好的,所以我们可以随意用。但是如果我们想用自己定义的属性名呢?这时候styleable的作用就出现了。我们只需要把attr的定义包围在styleable里面,这样定义的属性名就可以在style里面用。示例如下(示例来自上文给出的stackoverflow链接):

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
       <attr name="attrib1" format="string" />
     <declare-styleable name="blahblah">
        <attr name="attrib2" format="string" />
     </declare-styleable>

    在attrs.xml里面定义了两个attr,attrib1是普通的,attrib2包围在declare-styleable标签中;

    <com.custom.ViewClass  attrib1="xyz" attrib2="abc"/>

    我们可以在layout/someactivity.xml里直接使用这些attr;

    <style name="customstyle" parent="@android:style/Widget.TextView">
        <item name="attrib2">text value</item>
        <!--  customize other, standard attributes too: -->
        <item name="android:textColor">@color/white</item>
     </style>

    在styles.xml中,我们就能用attrib2。(原网站这里写成了attrib1,怀疑是笔误。)

    后来我验证过attrib1也能使用在style里面(我真的不确定,逻辑上应该不能才对,但是编译就是通过了。。。),那么这里就必须说明attr包不包含在styleable里面的另一个主要区别了,stackoverflow中是这么说的:

    The constructor of the custom class needs to read the styled and the non-styled attributes in a different way: the styled attributes with obtainStyledAttributes(), and the non-styled attributes with attr.getAttributeValue() or similar.

     也就是说,获取两者的方式不一样。获取attrib1用attr.getAttributeValue(),而获取attrib2用obtainStyledAttributes()。也就是说,styleable属性的获取方式具体可以参见android developer http://developer.android.com/intl/zh-CN/training/custom-views/create-view.html 这里我截取一段代码加以说明它的一般流程:

    public PieChart(Context ctx, AttributeSet attrs) {
       super(ctx, attrs);
       //得到styleable的全部值,返回是一个TypedArray。注意R.styleable.PieChart
       TypedArray a = context.getTheme().obtainStyledAttributes(
            attrs,
            R.styleable.PieChart,
            0, 0);
    
       try {
           //得到styleable里面的属性值。R.styleable.PieChart_showText
           mShowText = a.getBoolean(R.styleable.PieChart_showText, false);
           mTextPos = a.getInteger(R.styleable.PieChart_labelPosition, 0);
       } finally {
           a.recycle();
       }
    }

    为了保证a.recycle()被调用,把它用finally包起来。

    三、怎么移除与declare-styleable相关attr无用资源

    最后简单介绍一下我的工作,怎么移除这里面的无用资源呢?

    注意到,decleare-styleable中定义的attr在R.java中出现在两个地方:1)在class attr 中又有对应的变量;2)在class styleable中也有对应的变量。举个例子(截取的项目里面的一小部分,有改动):

    View Code

    我们在分析哪些attr没用到的时候是这么做的:

    1. 解析R.java,将class attr和class styleable中的变量分别存在两个集合里面,比如UnusedAttrSet和UnusedStyleableSet;
    2. 解析src下的代码和res下的代码,得到两个集合UsedAttrSet和UsedStyleableSet;
    3. 将UsedSet合并。因为用到的attr的可能是在styleable里面定义的,所以attr用了表示styleable也用了;用到styleable的肯定表示attr对应的量也用到了。
    4. 最后分别打印出attr和styleable中没有用到的量。

    这里有些同学可能会问,styleable集合肯定包含在attr里面吧?为什么还要找styleable呢?是的,可以直接判断attr有没有用到,这里我把它们独立主要是为了比如有个变量在attr和styleable中都没有用到,我就只需要去查找styleable就行了。这在调试代码的时候有用。

    处理的时候需要关注一下class attr和class styleable中的变量名略有不同。具体的实现如果有机会我专门开帖子来说明。

  • 相关阅读:
    图片上下左右居中
    点击滚动指定高度 屏幕滚动事件
    实例16 验证登录信息的合法性
    实例15 判断某一年是否为闰年
    实例14 实现两个变量的互换(不借助第3个变量)
    实例13 不用乘法运算符实现2*16
    实例12 用三元运算符判断奇数和偶数
    实例11 加密可以这样简单(位运算)
    实例10 自动类型转换与强制类型转换
    实例9 重定向输入流实现程序日志
  • 原文地址:https://www.cnblogs.com/wangfenjin/p/2672007.html
Copyright © 2020-2023  润新知