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
网友评论