在Gralde中包含许多的Task 和 Project ,但是里面还有一个很重要的概念 Extension,下面我们就来介绍一下Extension。
什么是Extension.
下面看一段非常常见的代码
android {
compileSdkVersion 30
defaultConfig {
applicationId "com.ljc.doubleclickplugin"
minSdkVersion 19
targetSdkVersion 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
上面这个 android 打包配置,就是 Gradle 的 Extension,翻译成中文意思就叫扩展。它的作用就是通过实现自定义的 Extension,可以在 Gradle 脚本中增加类似 android 这样命名空间的配置,Gradle 可以识别这种配置,并读取里面的配置内容。
如何定义Extension
ExtensionContainer
一般我们通过 ExtensionContainer 来创建 Extension,这个类与 TaskContainer 命名有点类似,TaskContainer 是用来创建并管理 Task 的,而 ExtensionContainer 则是用来创建并管理 Extension 的。通过 Project 的以下 API 可以获取到 ExtensionContainer 对象
ExtensionContainer getExtensions()
如何实现一个简单的Extension
//创建User
class User {
int age
String username
String toString() {
return "name = ${username}, age = ${age}"
}
}
//创建一个Extension 并定义名字
getExtensions().create("user", User)
//配置Extension
user {
age = 30
username = "xyy"
}
task testExt {
doLast{
//能直接通过 project 获取到自定义的 Extension
println project.user
}
}
运行结果
image.png
在上面的例子中 user就是我们自定义的Extension,我们需要配置的字段是和User的字段对应的,
我们可以通过project.user直接访问,每个 Extension 实际上与某个类是相关联的,在 build.gradle 中通过 DSL 来定义,Gradle 会识别解析并生成一个对象实例,通过该类可以获取我们所配置的信息。
ExtensionContainer主要API
1.创建
<T> T create(Class<T> publicType, String name, Class<? extends T> instanceType, Object... constructionArguments);
参数函数含义
publicType:创建的 Extension 实例暴露出来的类类型;
name:要创建的Extension的名字,可以是任意符合命名规则的字符串,不能与已有的重复,否则会抛异常;
instanceType:该Extension的类类型;
constructionArguments:类的构造函数参数值
示例
//父类
class Person {
String username
int age
Person(String name) {
username = name
}
void setAge(int age) {
this.age = age
}
String toString() {
return "Person name is $username, age is ${age} "
}
}
//子类
class User extends Person {
String sex
String owner
User(String sex, String owner) {
super("User")
this.sex = sex
this.owner = owner
}
String toString() {
return super.toString() + " sex is $age, owner is $owner."
}
}
//创建的Extension是 Animal 类型
Person mPerson = getExtensions().create(Person, "person", User, "man", "ljc")
//创建的Extension是 Pig 类型
User mUser = getExtensions().create("user", User, "women", "zdd")
person {
age = 4 //配置属性
}
user {
setAge 2 //这个是方法调用,也就是 setAge(2)
}
task testExt {
doLast {
println mPerson
println mUser
//验证 aPig 对象是 ExtensionAware 类型的
println "aPig is a instance of ExtensionAware : ${mUser instanceof ExtensionAware}"
}
}
运行结果
image.png
增加Extension
除了创建以外还有一个add方法可以增加Extension,与创建的区别就是他不会返回一个Extension对象。
下面一个简单示例看一下 添加方法
//添加一个User对象 添加名字为addUser 构造方法
getExtensions().add(User, "addUser", new User("man", "zmj"))
addUser {
username = "zms"
age = 25
sex = "man"
}
task addExt {
doLast {
def user = project.getExtensions().getByName("addUser")
println user
}
}
运行结果
查找Extension
Object findByName(String name)
<T> T findByType(Class<T> type)
Object getByName(String name) //找不到会抛异常
<T> T getByType(Class<T> type) //找不到会抛异常
比较简单跳过
嵌套Extension
就像最开始的例子就是一个嵌套的Extension,下面我们看一看嵌套的Extension如何实现
//首先定义和外部的Extension
class OutExt {
String outName
//这是内部的 Extension
InnerExt innerExt = new InnerExt()
void setOutName(String name) {
outName = name
}
void inner(Action<InnerExt> action) {
//创建内部Extension,并为其命名方法名 inner
action.execute(inner)
}
//创建一个方法名为inner大的内部Extension
void inner(Closure c) {
org.gradle.util.ConfigureUtil.configure(c, innerExt)
}
String toString() {
return "OuterExt[ name = ${outName}] " + innerExt
}
}
class InnerExt {
String innerName
void innerName(String name) {
innerName = name
}
String toString() {
return "InnerExt[ name = ${innerName}]"
}
}
def outExt = getExtensions().create("outer", OutExt)
outer {
outName "outer"
inner {
innerName "inner"
}
}
task outAndInExt {
doLast {
println outExt
}
}
运行结果
image.png
其中的关键方法在于
void inner(Action<InnerExt> action)
void inner(Closure c)
定义在 outer 内部的 inner ,Gradle 解析时实质上会进行方法调用,也就是会执行 outer.inner(...) 方法,而该方法的参数是一个闭包(俗称 Script Block),所以在类 OuterExt 中必须定义 inner(...) 方法。
Android的Extension
下面是一个android项目的经典配置
android {
compileSdkVersion 30
defaultConfig {
}
buildTypes {
productFlavors{
}
signingConfigs{
}
}
这就是一个很经典的扩展 我们进入源码去看一下
他们都是在 BaseExtension 的类里面
private final DefaultConfig defaultConfig;
private final NamedDomainObjectContainer<ProductFlavor> productFlavors;
private final NamedDomainObjectContainer<BuildType> buildTypes;
private final NamedDomainObjectContainer<SigningConfig> signingConfigs;
public void defaultConfig(Action<DefaultConfig> action) {
this.checkWritability();
action.execute(this.defaultConfig);
}
public void buildTypes(Action<? super NamedDomainObjectContainer<BuildType>> action) {
this.checkWritability();
action.execute(this.buildTypes);
}
public void productFlavors(Action<? super NamedDomainObjectContainer<ProductFlavor>> action) {
this.checkWritability();
action.execute(this.productFlavors);
}
public void signingConfigs(Action<? super NamedDomainObjectContainer<SigningConfig>> action) {
this.checkWritability();
action.execute(this.signingConfigs);
}
并且他们都是通过AppPlugin进行初始化的
初始化代码如下
protected AppExtension createExtension(
@NonNull DslScope dslScope,
@NonNull ProjectOptions projectOptions,
@NonNull GlobalScope globalScope,
@NonNull NamedDomainObjectContainer<BuildType> buildTypeContainer,
@NonNull DefaultConfig defaultConfig,
@NonNull NamedDomainObjectContainer<ProductFlavor> productFlavorContainer,
@NonNull NamedDomainObjectContainer<SigningConfig> signingConfigContainer,
@NonNull NamedDomainObjectContainer<BaseVariantOutput> buildOutputs,
@NonNull SourceSetManager sourceSetManager,
@NonNull ExtraModelInfo extraModelInfo) {
return project.getExtensions()
.create(
"android",
getExtensionClass(),
dslScope,
projectOptions,
globalScope,
buildOutputs,
sourceSetManager,
extraModelInfo,
new ApplicationExtensionImpl(
globalScope.getDslScope(),
buildTypeContainer,
defaultConfig,
productFlavorContainer,
signingConfigContainer));
}
网友评论