Extension
就是 Gradle 的 Extension,翻譯成中文意思就叫擴(kuò)展。它的作用就是通過(guò)實(shí)現(xiàn)自定義的 Extension,可以在 Gradle 腳本中增加類似 android 這樣命名空間的配置,Gradle 可以識(shí)別這種配置,并讀取里面的配置內(nèi)容。
一般我們通過(guò)ExtensionContainer來(lái)創(chuàng)建Extension,這個(gè)類跟TaskContainer命名有點(diǎn)類似。TaskContainer是用來(lái)創(chuàng)建并管理Task的,而ExtensionContainer則是用來(lái)創(chuàng)建并管理Extension的,通過(guò)Project的以下API可以獲取到ExtensionContainer對(duì)象
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:創(chuàng)建的 Extension 實(shí)例暴露出來(lái)的類類型;
- name:要?jiǎng)?chuàng)建的Extension的名字,可以是任意符合命名規(guī)則的字符串,不能與已有的重復(fù),否則會(huì)拋異常;
- instanceType:該Extension的類類型;
- constructionArguments:類的構(gòu)造函數(shù)參數(shù)值
相關(guān)代碼示例:
//在project中添加一個(gè)名為groupId的屬性
project.ext.groupId = "groupId"
// 使用ext塊添加擴(kuò)展屬性
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']
}
//打印各個(gè)擴(kuò)展屬性
task extParams {
println versionExt + " " + email
println android.each {
it.key + it.value
}
println dependence.each {
it.key + it.value
}
}
//創(chuàng)建自定義Extension
class MyDefaultConfig {
String applicationId
String versionCode
String versionName
int targetSdkVersion
@Override
String toString() {
return "applicationId = $applicationId , versionCode = $versionCode, versionName = $versionName, targetSdkVersion = $targetSdkVersion"
}
}
//創(chuàng)建一個(gè)名為 myDefaultConfig 的Extension,每個(gè) Extension 實(shí)際上與某個(gè)類是相關(guān)聯(lián)的
getExtensions().create("myDefaultConfig", MyDefaultConfig)
//配置extention
myDefaultConfig {
//myDefaultConfig里面能配置的屬性與類 MyDefaultConfig 中的字段是一致的
applicationId = "com.example"
versionName = "1.0.1"
versionCode = "1"
targetSdkVersion 31
}
task taskExt {
//能直接通過(guò) 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."
}
}
//創(chuàng)建的Extension是 暴露出來(lái)Animal 類型,創(chuàng)建extension名稱是name,該extension的類型是Pig,后面2個(gè)是參數(shù)
def aAnimal = getExtensions().create(Animal, "animal", Pig, 5, "pege")
//創(chuàng)建的Extension是 Pig 類型
def aPig = getExtensions().create(Pig, "pig", Pig, 3, "joge")
animal { //注:自定義擴(kuò)展和屬性沒(méi)有提示
legs = 4 //擴(kuò)展屬性配置對(duì)象值
}
pig {
setLegs(2)
}
task animalExt {
println aAnimal
println aPig
}
嵌套Extension : NamedDomainObjectContainer
什么是NamedDomainObjectContainer?
顧名思義就是命名領(lǐng)域?qū)ο笕萜?,它的主要功能有?/p>
- 通過(guò)DSL創(chuàng)建指定type的對(duì)象實(shí)例
- 指定的type必須有一個(gè)public構(gòu)造函數(shù),且必須帶有一個(gè)String name的參數(shù)
- 它是一個(gè)實(shí)現(xiàn)了SortedSet接口的容器,所以所有領(lǐng)域?qū)ο蟮膎ame屬性都必須是唯一的,在容器內(nèi)部會(huì)用name屬性來(lái)排序
NamedDomainObjectContainer 需要通過(guò) Project.container(...) API 來(lái)創(chuàng)建,其定義為:
<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
需要完成此種嵌套擴(kuò)展屬性定義:
android {
buildTypes {
release {
// 是否開(kāi)啟混淆
minifyEnabled true
// 開(kāi)啟ZipAlign優(yōu)化
zipAlignEnabled true
//去掉不用資源
shrinkResources true
// 混淆文件位置
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
// 使用release簽名
signingConfig signingConfigs.hmiou
}
debug {
signingConfig signingConfigs.hmiou
}
}
}
代碼示例:
// NamedDomainObjectContainer
//這是領(lǐng)域?qū)ο箢愋投x
class TestDomainObj {
//必須定義一個(gè) name 屬性,并且這個(gè)屬性值初始化以后不要修改
String name
String msg
//構(gòu)造函數(shù)必須有一個(gè) name 參數(shù)
public TestDomainObj(String name) {
this.name = name
}
void msg(String msg) {
this.msg = msg
}
String toString() {
return "name = ${name}, msg = ${msg}"
}
}
//創(chuàng)建一個(gè)擴(kuò)展
class TestExtension {
//定義一個(gè) NamedDomainObjectContainer 屬性
NamedDomainObjectContainer<TestDomainObj> testDomains
public TestExtension(org.gradle.api.Project project) {
//在構(gòu)造函數(shù)中通過(guò) project.container(...) 方法創(chuàng)建 NamedDomainObjectContainer
testDomains = project.container(TestDomainObj)
}
//讓其支持 Gradle DSL 語(yǔ)法,注:該方法名要與Extension第二層的name一致
void buildTypes(Action<NamedDomainObjectContainer<TestDomainObj>> action) {
action.execute(testDomains)
}
void test() {
//遍歷命名領(lǐng)域?qū)ο笕萜?,打印出所有的領(lǐng)域?qū)ο笾? testDomains.all {
println(it)
}
}
}
//創(chuàng)建一個(gè)名為 test 的 Extension
def testExt = getExtensions().create("myandroid", TestExtension, project)
//該第三個(gè)參數(shù)project就傳到TestExtention對(duì)象的構(gòu)造參數(shù)中
//給 TextExtention對(duì)象配置 NamedDomainObjectContainer 屬性
myandroid {
buildTypes {
release {
msg "This is release config"
}
debug {
msg "This is debug config"
}
}
}
task nameDomainTask {
testExt.test() //執(zhí)行TextExtention對(duì)象的test方法,打印配置的各個(gè)屬性
//domainx配置就成為了默認(rèn)、必須的name屬性 內(nèi)部配置了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