Gradle之自定义Extension

作者: 奔跑吧李博 | 来源:发表于2023-11-22 15:36 被阅读0次
    Extension

    就是 Gradle 的 Extension,翻译成中文意思就叫扩展。它的作用就是通过实现自定义的 Extension,可以在 Gradle 脚本中增加类似 android 这样命名空间的配置,Gradle 可以识别这种配置,并读取里面的配置内容。

    一般我们通过ExtensionContainer来创建Extension,这个类跟TaskContainer命名有点类似。TaskContainer是用来创建并管理Task的,而ExtensionContainer则是用来创建并管理Extension的,通过Project的以下API可以获取到ExtensionContainer对象

    ExtensionContainer getExtensions()
    
    ExtensionContainer主要api及用法
    <T> T create(String name, Class<T> type, Object... constructionArguments)
    <T> T create(Class<T> publicType, String name, Class<? extends T> instanceType, Object... constructionArguments)
    
    • publicType:创建的 Extension 实例暴露出来的类类型;
    • name:要创建的Extension的名字,可以是任意符合命名规则的字符串,不能与已有的重复,否则会抛异常;
    • instanceType:该Extension的类类型;
    • constructionArguments:类的构造函数参数值
    相关代码示例:
    //在project中添加一个名为groupId的属性
    project.ext.groupId = "groupId"
    
    // 使用ext块添加扩展属性
    ext {
        versionExt = "1.0.2"
        email = "test@gihhub.com"
        artifactId='EasyDependency'
        config=[
                key:'value'
        ]
        android = [compileSdkVersion   : 25,
                   buildToolsVersion   : '25.0.0',
                   applicationId       : 'com.youdu',
                   minSdkVersion       : 16,
                   targetSdkVersion    : 23,
                   versionCode         : 1,
                   versionName         : '1.0.0']
        signConfigs = ['storeFile'    : 'abc.jks',
                       'storePassword': '123456',
                       'keyAlias'     : 'abc',
                       'keyPassword'  : '123456']
        dependence = ['libSupportV7'           : 'com.android.support:appcompat-v7:25.0.0',
                      'libSupportMultidex'     : 'com.android.support:multidex:1.0.1']
    }
    
    //打印各个扩展属性
    task extParams {
        println versionExt + " " + email
        println android.each {
            it.key + it.value
        }
        println dependence.each {
            it.key + it.value
        }
    }
    
    //创建自定义Extension
    class MyDefaultConfig {
        String applicationId
        String versionCode
        String versionName
        int targetSdkVersion
        @Override
        String toString() {
            return "applicationId = $applicationId , versionCode = $versionCode, versionName = $versionName, targetSdkVersion = $targetSdkVersion"
        }
    }
    //创建一个名为 myDefaultConfig 的Extension,每个 Extension 实际上与某个类是相关联的
    getExtensions().create("myDefaultConfig", MyDefaultConfig)
    //配置extention
    myDefaultConfig {
        //myDefaultConfig里面能配置的属性与类 MyDefaultConfig 中的字段是一致的
        applicationId = "com.example"
        versionName = "1.0.1"
        versionCode = "1"
        targetSdkVersion 31
    }
    task taskExt {
        //能直接通过 project 获取到自定义的 Extension
        println project.myDefaultConfig
    }
    //打印 applicationId = com.example , versionCode = 1, versionName = 1.0.1, targetSdkVersion = 31
    
    
    //父类
    class Animal {
        String username
        int legs
        Animal(String name) {
            username = name
        }
    
        void setLegs(int c) {
            legs = c
        }
    
        String toString() {
            return "This animal is $username, it has ${legs} legs."
        }
    }
    
    //子类
    class Pig extends Animal {
        int age
        String owner
    
        Pig(int age, String owner) {
            super("Pig")
            this.age = age
            this.owner = owner
        }
    
        String toString() {
            return super.toString() + " Its age is $age, its owner is $owner."
        }
    }
    //创建的Extension是 暴露出来Animal 类型,创建extension名称是name,该extension的类型是Pig,后面2个是参数
    def aAnimal = getExtensions().create(Animal, "animal", Pig, 5, "pege")
    //创建的Extension是 Pig 类型
    def aPig = getExtensions().create(Pig, "pig", Pig, 3, "joge")
    animal { //注:自定义扩展和属性没有提示
        legs = 4 //扩展属性配置对象值
    }
    pig {
        setLegs(2)
    }
    task animalExt {
        println aAnimal
        println aPig
    }
    
    嵌套Extension : NamedDomainObjectContainer

    什么是NamedDomainObjectContainer?

    顾名思义就是命名领域对象容器,它的主要功能有:

    • 通过DSL创建指定type的对象实例
    • 指定的type必须有一个public构造函数,且必须带有一个String name的参数
    • 它是一个实现了SortedSet接口的容器,所以所有领域对象的name属性都必须是唯一的,在容器内部会用name属性来排序

    NamedDomainObjectContainer 需要通过 Project.container(...) API 来创建,其定义为:

    <T> NamedDomainObjectContainer<T> container(Class<T> type)
    <T> NamedDomainObjectContainer<T> container(Class<T> type, NamedDomainObjectFactory<T> factory)
    <T> NamedDomainObjectContainer<T> container(java.lang.Class<T> type, Closure factoryClosure

    需要完成此种嵌套扩展属性定义:

    android {
        buildTypes {
            release {
                // 是否开启混淆
                minifyEnabled true
                // 开启ZipAlign优化
                zipAlignEnabled true
                //去掉不用资源
                shrinkResources true
                // 混淆文件位置
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
                // 使用release签名
                signingConfig signingConfigs.hmiou
            }
            debug {
                signingConfig signingConfigs.hmiou
            }
        }
    }
    
    代码示例:
    //  NamedDomainObjectContainer
    //这是领域对象类型定义
    class TestDomainObj {
        //必须定义一个 name 属性,并且这个属性值初始化以后不要修改
        String name
        String msg
    
        //构造函数必须有一个 name 参数
        public TestDomainObj(String name) {
            this.name = name
        }
    
        void msg(String msg) {
            this.msg = msg
        }
    
        String toString() {
            return "name = ${name}, msg = ${msg}"
        }
    }
    
    //创建一个扩展
    class TestExtension {
        //定义一个 NamedDomainObjectContainer 属性
        NamedDomainObjectContainer<TestDomainObj> testDomains
    
        public TestExtension(org.gradle.api.Project project) {
            //在构造函数中通过 project.container(...) 方法创建 NamedDomainObjectContainer
            testDomains = project.container(TestDomainObj)
        }
    
        //让其支持 Gradle DSL 语法,注:该方法名要与Extension第二层的name一致
        void buildTypes(Action<NamedDomainObjectContainer<TestDomainObj>> action) {
            action.execute(testDomains)
        }
    
        void test() {
            //遍历命名领域对象容器,打印出所有的领域对象值
            testDomains.all {
                println(it)
            }
        }
    }
    
    //创建一个名为 test 的 Extension
    def testExt = getExtensions().create("myandroid", TestExtension, project)
    //该第三个参数project就传到TestExtention对象的构造参数中
    
    //给 TextExtention对象配置 NamedDomainObjectContainer 属性
    myandroid {
        buildTypes {
            release {
                msg "This is release config"
            }
            debug {
                msg "This is debug config"
            }
        }
    }
    
    task nameDomainTask {
        testExt.test() //执行TextExtention对象的test方法,打印配置的各个属性
        //domainx配置就成为了默认、必须的name属性 内部配置了msg属性
    }
    //打印
    //name = debug, msg = This is debug config
    //name = release, msg = This is release config
    

    参考:
    https://juejin.cn/post/6844903838290296846#comment
    demo参考:
    https://github.com/running-libo/GradleStudy

    相关文章

      网友评论

        本文标题:Gradle之自定义Extension

        本文链接:https://www.haomeiwen.com/subject/kfwyedtx.html