常见优化:资源冲突的处理

前言

什么是资源冲突

引用第三方库或者子Module时,这些依赖库中的资源可能会与主工程本身的资源发生重名冲突,从而发生资源互相覆盖的情况

容易导致什么问题

  1. 项目引用drawable资源、string资源等可能不会按照自己预期的效果来显示
  2. layout资源如果错误,甚至会导致无法通过id获取到对应控件,从而触发如空指针等一系列崩溃问题
    以上的问题都是可能需要到运行时才会发现的

处理办法

修改资源前缀

可以通过在model的gradle文件里加上下面的字段

android{
    resourcePrefix 'a_'
}

注意:上面只是加上了限制,让你的module不按照前缀规范(如a_activity_main.xml)来命名的资源会在编译器中报错,并且此报错并不会影响编译…所以这个方法仅仅适用于小项目或者项目的初期

通过CheckResourceConflict工具

CheckResourceConflict的github地址

工具作用

新增了一个task,可以用来遍历所有资源文件,根据他们所在的目录与文件名/资源名组成id,之后比较它们的id即可

如何生成task并获取所有资源文件
class CheckResourcePrefixPlugin implements Plugin<Project> {
    @Override
    void apply(Project project) {
        project.afterEvaluate {
            variants.forEach { variant ->
                variant as BaseVariantImpl
                def thisTaskName = "checkResource${variant.name.capitalize()}"
                //每个variant都创建一个任务
                def thisTask = project.task(thisTaskName)
                thisTask.group = "check"
                thisTask.doLast {
                    //这里获取到了所有资源文件
                    def files = variant.allRawAndroidResources.files
                }
            }
        }
    }
}

如何区分资源

根据所在父文件夹、文件名/资源名来判断是否会冲突

//FileResource.java
public String getUniqueId() {
    //在drawable或者mipmap文件夹中
    //例:file@drawable-v4/abc
    return this.lastDirectory != null && (this.lastDirectory.startsWith("drawable-") 
    || this.lastDirectory.startsWith("mipmap-")) 
    && !this.lastDirectory.contains("-v") ? "file@" + this.lastDirectory + "-v4/" + this.fileName : "file@" + this.lastDirectory + "/" + this.fileName;
}
//ValueResource.java
public String getUniqueId() {
    //例:value@values/app_name
    return "value@" + this.lastDirectory + "/" + this.resName;
}

AndResGuard进行资源混淆

详见WeMobileDev公众号文章

作用

抄自官方解释:AndResGuard是一个帮助你缩小APK大小的工具,他的原理类似Java Proguard,但是只针对资源。他会将原本冗长的资源路径变短,例如将res/drawable/wechat变为r/d/a。

自己的理解
  1. 它会把原本冗长的资源路径变短,例如将res/drawable/wechat变为r/d/a,从而减少apk大小,并且让别人
  2. 它从字节码层面修改了resources.arsc文件(即资源的引用路径、值的索引表),它把里面的name换成了相同值,并指向了我们所修改了路径的资源文件,从而也节省了部分空间
  3. 注意修改name会导致Resources的getIdentifier无效,就是无法通过name反查id,这会与android-skin-support换肤框架冲突,所以如果有这些api或者框架的使用,需要在框架中通过相应配置关闭name的重写
最终apk打包的效果

name都变了
res文件已经被修改

引用

Android | 资源冲突覆盖的一些思考
Android 组件资源覆盖冲突解决方案

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值