向工程腐化开炮|资源治理

作者:刘天宇(谦风)

系列文章回顾《向工程腐化开炮 | proguard治理》《向工程腐化开炮 | manifest治理》《向工程腐化开炮:Java代码治理》。本文为系列文章第四篇,聚焦于Android 资源,这一细分领域。对工程腐化,直接开炮!

准确的说,本文主角是Android资源,而java资源归属到java代码治理范畴,并在《向工程腐化开炮:Java代码治理》一文中给出了应对方案。

Android资源从定义和使用方式来看,可以分为Resource和Asset两个大类。前者提供受控的结构化访问方式,每个资源均有唯一id标识,以及多种配置限定符来支持多语言、多设备、多特性等能力;后者提供原始且相对自由的目录和文件访问。Resource类型是绝大部分资源使用场景下的最佳选择,本文主要聚焦的即是这种类型资源,对冲突、无用、缺失类引用、硬编码文本,这几种腐化情况,开展工具研发,以及治理实践。

基础知识

本章先简要介绍一些基础知识,方便大家对Android资源有一个“框架性”的清晰认知,为理解第二章治理实践内容打下基础。此外,也尝试以独特视角,来讲解一些有趣的技术点。

1.1 资源分类

对于Resource资源,按照使用场景,官方文档已经给出了划分和具体说明。本节以资源编译后,对应R内部类的类型,给出一个分类:

以上24种资源,均可以通过R.<type>.<name>形式在java代码中引用,其中一些还可以通过@<type>/<name>形式在manifest和资源中引用。对上述分类中「是否独立文件」、「是否位于resources.arsc」两个维度进行一些解读:

  • 是否独立文件。一个资源如果对应一个完整的独立文件,这种属于File-Base Resource,在最终apk的res目录下也会存在一份对应文件;否则,属于Value-Base Resource,在apk中没有独立文件与之对应,其值(如果有)存储在resources.arsc中。其中color类型比较特殊,单一color资源是Value-Base,但是颜色状态列表(ColorStateList)属于File-Base。此外,是否独立文件,是从资源编译后这一视角来看的,在定义资源时,Android提供了一种内嵌xml资源的形式,可以把多个独立文件类型资源,写在一个xml文件中,在此不展开讨论;
  • 是否位于resources.arsc。绝大部分资源,在R$<type>类中field的取值,都是0x7fxxxxxx,并且在resources.arsc中都有一条对应记录。对于File-Base资源,记录值是file的相对路径,对于Value-Base资源,记录值就是资源值本身。需要注意的是,styleable类型资源比较特殊,仅存在于R$styleable类中,其field取值也并不是0x7fxxxxxxx格式,而是整型或整型数组,并且在resources.arsc中并不存在。

通过一个styleable定义示例,来帮助我们理解上述知识:

# 资源定义于 res/value/attrs.xml
<resources>
    <declare-styleable name="DeclareStyleable1" >
        <attr name="attr_enum" format="enum">
            <enum name="attrEnum1" value="1"/>
            <enum name="attrEnum2" value="2"/>
        </attr>
        <attr name="attr_integer" format="integer"/>
        <attr name="android:padding" format="dimension"/>
    </declare-styleable>
</resources>

在apk编译过程中,生成以下R.java代码:

# R.java文件中,生成以下代码
public static final class id {
    public static final int attrEnum1=0x7f060000;
    public static final int attrEnum2=0x7f060001;
}
public static final class attr {
    public static final int attr_enum=0x7f020000;
    public static final int attr_integer=0x7f020001;
}
 
public static final class styleable {
    public static final int[] DeclareStyleable1 = {0x010100d5, 0x7f020000, 0x7f020001};
    public static final int DeclareStyleable1_android_padding=0;
    public static final int DeclareStyleable1_attr_enum=1;
    public static final int DeclareStyleable1_attr_integer=2;
}

最后,在resources.arsc中,生成以下记录:

# resources.arsc中,生成记录
type | id           | name         | value
id     0x7f060000     attrEnum1      None
id     0x7f060001     attrEnum2      None
attr   0x7f020000     attr_enum      1,2
attr   0x7f020001     attr_integer   0

一个styleable定义,最终会生成一连串产物,由此可见,Android资源的处理逻辑,相对还是比较复杂的。在这个例子中,还有几个有意思的技术点,值得拿来讲一讲:

  • 一个attr,name使用android:xxxx,在R.java和resources.arsc中不会生成对应内容,因此在语意可复用时,使用系统提供的attr,可以节省一点包大小空间;
  • 如果多个styleable或者style,定义了同名attr,实际只会生成一个attr资源,相当于提高了复用度;
  • attrEnum1、attrEnum2这种id类型资源,如果其它类型资源(例如layout)中也有同名定义,那么实际也只会生成一个id资源,同样也提高了复用度。

好了࿰

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值