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


一、style的作用

首先需要了解style的作用是什么!Android developerhttp://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 withobtainStyledAttributes(), and the non-styled attributes withattr.getAttributeValue()or similar.

也就是说,获取两者的方式不一样。获取attrib1用attr.getAttributeValue(),而获取attrib2用obtainStyledAttributes()。也就是说,styleable属性的获取方式具体可以参见android developerhttp://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中的变量名略有不同。具体的实现如果有机会我专门开帖子来说明。

更多相关文章

  1. android,自定义广播,最终广播接收者,防止拦截广播,有序广播,无序广
  2. Android中visibility属性
  3. android之xml解析
  4. 【Android(安卓)XML】Android(安卓)XML 转 Java Code 系列之 Sel
  5. [置顶] 深入了解Android进度条——ProgressBar,SeekBar和RatingBa
  6. android 自定义ripple水波纹点击效果
  7. android intent-filter
  8. android 开发文档翻译
  9. android setCompoundDrawables和setCompoundDrawablesWithIntrin

随机推荐

  1. Flask学习之旅--分页功能:分别使用 flask-
  2. EXCEL函数篇—9大类文本函数
  3. FFmpeg编译4.1.4并移植到Android
  4. 拒绝月薪18k的数据分析工作,why?
  5. 月薪5K和月薪2W的运营之间的区别,究竟在哪
  6. C/C++程序从文本文件中读取(保存)数据
  7. crmeb 知识付费系统-首页说明-看云
  8. 【linux】循序渐进学运维-CentOS7基本配
  9. 10天入门go语言教程- 常量变量
  10. 深圳高新技术企业认定常见问题及相关材料