利用Android Gradle进行自动化设置资源名命名规则

news/2024/5/20 1:02:15 标签: android, 自动化, gradle

文章目录

      • 一、背景描述:
      • 二、思路分析
      • 三、问题解决与实现
      • 四、工具的使用
      • 五、结论与展望

一、背景描述:

    公司再不断推进组件化,多个Module开发。随着Module越来越多,当然也存在许多需要注意的问题。是无法保证多个Module中的资源命名完全不同,就可能会出现资源引用问题,造成资源冲突。

二、思路分析

     用Gradle配置,在android 中设置 resourcePrefix 属性,前缀字符串根据实际情况自定义。
     但是因为Module太多,每添加一个模块就需要在Modulebuild.gradle里进行配置, 这样太繁琐,不够智能,那么怎么解决呢,思路如下:

     1、写一个Task,生成一个json文件,里面以key->value的形式存储模块名和其对应的前缀。

     2、将json文件中前缀value进行修改,每次task执行更新不会覆盖之前修改过的value,默认前缀名是模块名。

     3、在所有模块Gradle都配置完之后,给每个模块设置一下修改后的前缀属性

效果展示:

    编译器会这样提示,但是编译的时候不会报错在这里插入图片描述

三、问题解决与实现

步骤1:写一个更新/生成命名json文件的task
    这个task我们暂时写到 appbuild.gradle文件中,写在别的.gradle文件中也可以

task moduleNameToJson() {

    doLast {
        def jsonFile = file('./ResourceNameRule.json')
        def mapResult = new HashMap<String, String>()
        // 每次新建的module不会覆盖之前修改过的value
        if (jsonFile.exists()){
            def parsedJson = new JsonSlurper().parseText(jsonFile.text)
            parsedJson.each {
                mapResult.put(it.key.toString(), it.value.toString())
            }
            mapResult = loopGetName(mapResult, rootProject)
        }else{
            mapResult = loopGetName(null, rootProject)
        }
        println mapResult.toString()
        try{
            def  writer = new FileWriter("./app/ResourceNameRule.json")
            def  gson = new Gson().newBuilder().create()
            gson.toJson(mapResult, writer)
            writer.flush()
            writer.close()
        }catch (Exception e) {}
    }

}

/**
 * 给所有模块名处理命名
 *
 * @param hashmap 有json文件就传入旧map
 * @param project 执行时期的功能
 * @return HashMap
 */
private static HashMap<String,String> loopGetName(HashMap<String, String> hashmap, Project project){
    def map
    if(hashmap!=null){
        map = hashmap
    }else{
        map = new HashMap<String, String>()
    }

    project.allprojects {
        def childAndroid = null
        try {
            childAndroid = it.extensions.getByType(AppExtension.class)
        } catch (Exception e) {}
        try {
            if (childAndroid == null) {
                childAndroid = it.extensions.getByType(LibraryExtension.class)
            }
        } catch (Exception e) {}
        if (childAndroid != null)  {
        // module命名 最好以module_XXX 这样,这里可以自己对模块名进行处理
            def prefix = "${it.name}".replace("module_", "")
            if (hashmap == null){
                if (prefix != null){
                    map.put(it.name, prefix)
                }
            }else{
                if (map.get(it.name) == null || map.get(it.name) == ""){
                    map.put(it.name, prefix)
                }
            }
        }
    }
    return map
}

步骤二: 把json文件进行修改
在这里插入图片描述
步骤三: 点击sync时,将前缀属性设置到每个Module中

Hook点:
在这里插入图片描述
Gradle构建周期中的Hook点
                                                Gradle构建周期中的Hook点

    要给每个module都设置属性就要考虑Gradle执行的生命周期了,不然获取到也是空的。这里我们选择在gradle.afterProject时期进行hook,读取配置好的json文件,给每个Module设置前缀规则,这个我们也暂时写到app的build.gradle中,代码如下:

gradle.afterProject {
    // 获取资源命名规则的配置文件
    def jsonFile = file('./ResourceNameRule.json')
    if (jsonFile.exists()){
        def parsedJson = new JsonSlurper().parseText(jsonFile.text)
        rootProject.allprojects {
            def childAndroid = null
            try  {
                childAndroid = it.extensions.getByType(AppExtension.class)
            } catch (Exception e) {
            }
            try {
                if (childAndroid == null) {
                    childAndroid = it.extensions.getByType(LibraryExtension.class)
                }
            } catch (Exception e) {
            }
            try {
                if (childAndroid != null) {
                    parsedJson.each { entry ->
                    // 这里可以对模块进行过滤
                        if ("libMatisse" == entry.key.toString()){
                            return
                        }
                        if (entry.key.toString() == it.name) {
                            childAndroid.resourcePrefix(entry.value.toString())
                        }

                    }
                }
            } catch (Exception e) {
                childAndroid = null
                return
            }
        }
    }
}

四、工具的使用

1、每次添加新Module之后,先运行task,生成新的json文件或者更新 新的模块到json文件中。
在这里插入图片描述
2、把json文件中的前缀修改成你想要的前缀
3、点击大象,sync一下,就全局设置啦
在这里插入图片描述

五、结论与展望

     如此就可以进行自动化设置资源名的前缀属性,前缀字符串也可以动态配置,非常的方便。随着模块越来越多,这样做的效果只会越来越明显,不按照规则起名字不会导致编译报错,但是资源名重复会导致编译报错。规范命名总是好的。

     但项目也有点小缺陷,目前是将代码写到了app下的build.gradle里,导致该文件代码比较多。未来可以优化,单独建一个.gradle文件进行封装,大佬们提提思路,现在遇到的问题是Gson不能在其他的.gradle中使用。代码写的也比较冗余,还不够精简,进步的空间还挺大,加油,奥里给!


http://www.niftyadmin.cn/n/793636.html

相关文章

【10】Kotlin项目实操之首页模块

&#xff08;1&#xff09;一个人只要自己不放弃自己&#xff0c;整个世界也不会放弃你. &#xff08;2&#xff09;天生我才必有大用 &#xff08;3&#xff09;不能忍受学习之苦就一定要忍受生活之苦&#xff0c;这是多么痛苦而深刻的领悟. &#xff08;4&#xff09;做难事必…

【11】Kotlin项目实操之高阶函数二

&#xff08;1&#xff09;一个人只要自己不放弃自己&#xff0c;整个世界也不会放弃你. &#xff08;2&#xff09;天生我才必有大用 &#xff08;3&#xff09;不能忍受学习之苦就一定要忍受生活之苦&#xff0c;这是多么痛苦而深刻的领悟. &#xff08;4&#xff09;做难事必…

【12】Kotlin函数泛型协程

&#xff08;1&#xff09;一个人只要自己不放弃自己&#xff0c;整个世界也不会放弃你. &#xff08;2&#xff09;天生我才必有大用 &#xff08;3&#xff09;不能忍受学习之苦就一定要忍受生活之苦&#xff0c;这是多么痛苦而深刻的领悟. &#xff08;4&#xff09;做难事必…

【01】自定义View与高级UI

&#xff08;1&#xff09;什么是自定义View?什么是高级UI&#xff1f; &#xff08;2&#xff09;LayoutParams解析原理 &#xff08;3&#xff09;MeasureSpec原理解析 &#xff08;4&#xff09;自定义流式布局项目实战 &#xff08;5&#xff09;坐标系介绍 &#xff08;6…

【45】AndroidStudio引入的依赖库classes.jar中找不到类

&#xff08;1&#xff09;AndroidStudio引入的依赖库classes.jar中找不到类 &#xff08;2&#xff09;项目引入androidx.appcompat:appcompat:$dependVersion.appcompact &#xff08;3&#xff09;appcompat版本1.3.0 &#xff08;4&#xff09;在项目的External Libraries库…

【02】ViewPager高度自适应轮播图

&#xff08;1&#xff09;高度自适应ViewPager &#xff08;2&#xff09;解决ViewPager设置高度为wrap_content无效的方法 【02】ViewPager高度自适应轮播图 文章目录【02】ViewPager高度自适应轮播图1.效果2.源码2.1自定义ViewPager2.1Activity2.3PagerAdapter2.4切换特效2.…

【02】布局原理与XML原理分析

&#xff08;1&#xff09;使用插件化的方案为App换肤 &#xff08;2&#xff09;不需要重启App就能够换肤 &#xff08;3&#xff09;市场上所有的APP都可以当成自己的皮肤包来用。 &#xff08;4&#xff09;无闪烁 &#xff08;5&#xff09;便于扩展与维护&#xff0c;入侵…

【03】布局原理与XML原理分析二

&#xff08;1&#xff09;使用插件化的方案为App换肤 &#xff08;2&#xff09;不需要重启App就能够换肤 &#xff08;3&#xff09;市场上所有的APP都可以当成自己的皮肤包来用。 &#xff08;4&#xff09;无闪烁 &#xff08;5&#xff09;便于扩展与维护&#xff0c;入侵…