Gradle 之扩展Extension类 (七)
- Gradle 之Groovy基本语法(一)
- Gradle 之Groovy文件操作(二)
- Gradle 之详解Project(三)
- Gradle 之详解Task(四)
- Gradle 之初识插件(五)
- Gradle 之常用配置(六)
- Gradle 之扩展Extension类 (七)
一、前言
先看下Android中默认的扩展:
android { compileSdkVersion 23 buildToolsVersion = '23.0.3' defaultConfig { applicationId "com.phj.gradle" minSdkVersion 19 targetSdkVersion 22 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } debug { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } }}
Gradle允许将“命名空间”DSL扩展添加到目标对象。这么一大坨代码是通过设置好Android扩展后,最终才能按照相应的规则写的。他通过给用户提供相对于的配置方法,在编译打包期间,通过用户相对应的配置,再做出相应的行为。
二、自定义扩展
现在我们就创建一个和android{}类似的配置,配置格式如下:
classes { className 'className' person { name 'phj' age 24 }}
1)、创建Groovy类
因为是两层闭包,所以需要建立两个类,他们分别是Classes 和Person 类。Classes中会Person类的成员变量,如下:
class Classes { String className Person person = new Person() void className(String className){ this.className = className; } void person(Action action){ action.execute(person) } @Override String toString() { "className = ${this.className}, ${person}" }}class Person { int age String name void age(int age){ this.age = age } void name(String name){ this.name = name } String toString() { "Person:age = ${age}, name = ${name}" }}
Classes类和Person是怎么关联起来的:
void person(Action action){ action.execute(person) }
或者:
void person(Closure c) { ConfigureUtil.configure(c, person) }
这样就可以在classes闭包中使用person。
2)、添加到ExtensionContainer
getExtensions().add("classes", Classes)
通过getExtensions()可以拿到当前Project对象的ExtensionContainer,将写好的extension添加到ExtensionContainer
ExtensionContainer类:
public interface ExtensionContainer { void add(String name, Object extension); T create(String name, Class type, Object... constructionArguments); T getByType(Class type) throws UnknownDomainObjectException; T findByType(Class type); Object getByName(String name) throws UnknownDomainObjectException; Object findByName(String name); @Incubating void configure(Class type, Action<? super T> action); ExtraPropertiesExtension getExtraProperties();}
ExtensionContainer类相当于一个集合,主要包含了存储和查找方法。
- add : 向ExtensionContainer添加一个extension
- create : 创建一个extension对象,并返回该扩展
- getByType :通过Type查找extension,没有找到会有异常
- findByType :通过Type查找extension,没有找到会无异常
- getByName :通过Name查找extension,没有找到会有异常
- findByName :通过Name查找extension,没有找到会无异常
3)、获取配置
通过前两步即完成了配置,现在在脚本中可以写下下面的配置了,现在的工作就是获取该配置
classes { className 'className' person { name 'phj' age 24 }}
通过ExtensionContainer获取:
def extension = project.getExtensions().getByName("classes") as Classes println extension.className
三、NamedDomainObjectContainer类
1)、定义
Android中的扩展和NamedDomainObjectContainer共用的,他可以创建一个自定义名字的实例。
如buildTypes中release和debug 等:
release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } debug { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' }
或者dev和free:
productFlavors{ dev{ manifestPlaceholders = ["test_key": "测试版key"] } free{ applicationIdSuffix ".free" manifestPlaceholders = ["test_key": "Free版key"] } }
这些都是用户自己添加的名字,事先并没定义。
2)、实现
- groovy代码
class Classes { NamedDomainObjectContainer container public Classes(Project project) { container = project.container(Person) } void person(Action> action){ action.execute(container) } @Override String toString() { "className = ${this.className}, ${person}" }}class Person { String name int age public Person(String name) { this.name = name } void age(int age){ this.age = age } String toString() { "Person:age = ${age}, name = ${name}" }}
使用NamedDomainObjectContainer的方式和之前没有的本质是一样的,如之前的Classes中有Person成员变量,现在需要时NamedDomainObjectContainer
- 添加到ExtensionContainer
def ext = getExtensions().create("classes", Classes, project) as Classes
配置如下:
classes { person { person1 { age 21 } person2 { age 22 } person3 { age 23 } }}
- 获取
ext.container.each { value-> println value }
最终输出:
Person:age = 21, name = person1Person:age = 22, name = person2Person:age = 23, name = person3
获取NamedDomainObjectContainer对象
获取NamedDomainObjectContainer对象的方法是在project中,这样在构建Classes的时候就需要将当前的Project对象传入进来,这样就可能根据该对象获取Person相关的NamedDomainObjectContainer对象。
project中获取方法如下:主要是通过传入类类型,返回一个当前类型的NamedDomainObjectContainer对象。
/** * Creates a container for managing named objects of the specified type. The specified type must have a public constructor which takes the name as a String parameter.
* *
All objects MUST expose their name as a bean property named "name". The name must be constant for the life of the object.
* * @param type The type of objects for the container to contain. * @param The type of objects for the container to contain. * @return The container. */ NamedDomainObjectContainer container(Class type); /** * Creates a container for managing named objects of the specified type. The given factory is used to create object instances.
* * All objects MUST expose their name as a bean property named "name". The name must be constant for the life of the object.
* * @param type The type of objects for the container to contain. * @param factory The factory to use to create object instances. * @param The type of objects for the container to contain. * @return The container. */ NamedDomainObjectContainer container(Class type, NamedDomainObjectFactory factory); /** * Creates a container for managing named objects of the specified type. The given closure is used to create object instances. The name of the instance to be created is passed as a parameter to * the closure.
* * All objects MUST expose their name as a bean property named "name". The name must be constant for the life of the object.
* * @param type The type of objects for the container to contain. * @param factoryClosure The closure to use to create object instances. * @param The type of objects for the container to contain. * @return The container. */ NamedDomainObjectContainer container(Class type, Closure factoryClosure);
container(Class type)
上面的container(Class
也可以在类外包装
// 1、groovy类class P { String name int age public P(String name) { this.name = name } void age(int age){ this.age = age } String toString() { "P:age = ${age}, name = ${name}" }}// 2、采用NamedDomainObjectContainer包装def p = container(P) as NamedDomainObjectContainer// 3、添加到扩展容器中project.extensions.add('platform',p)// 4、编写脚本platform { wandoujia { age = 1 } xiaomi { age = 2 }}
本质是一样的,不过多说明:
- 1、编写groovy类
- 2、采用NamedDomainObjectContainer包装
- 3、添加到扩展容器中
- 4、编写脚本
四、android{} 常用配置
android { compileSdkVersion 23 buildToolsVersion = '23.0.3' defaultConfig { applicationId "com.phj.gradle" minSdkVersion 19 targetSdkVersion 23 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } debug { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } dexOptions{ dexInProcess true javaMaxHeapSize "4g" } productFlavors { wandoujia { minSdkVersion 19 targetSdkVersion 23 versionCode 1 versionName "1.0" versionNameSuffix 'phj' } } externalNativeBuild{ ndkBuild{ path file("src\\main\\jni\\Android.mk") } cmake { path "src/main/cpp/CMakeLists.txt" } } lintOptions { abortOnError false } packagingOptions { exclude ['lib/armeabi-v7a/libavcodec-57.so', 'lib/armeabi-v7a/libavdevice-57.so'] } signingConfigs { config { keyAlias '...' keyPassword '...' storeFile file('...') storePassword '...' } } sourceSets { main { java.srcDirs 'src/main/java','src/main/java2' manifest.srcFile 'src/main/AndroidManifest.xml' resources.srcDirs = ['src/main/res'] res.srcDirs = ['src/main/res'] assets.srcDirs = ['src/main/assets'] jniLibs.srcDirs = ['../lib'] } }}
android是com.android.build.gradle包下的AppExtension类,所有能设置的属性都在该类的方法中。主要在其父类BaseExtension中设置的。
BaseExtension中的属性如下:
private final List> transformDependencies = Lists.newArrayList(); private final AndroidBuilder androidBuilder; private final SdkHandler sdkHandler; private final ProductFlavor defaultConfig; private final AaptOptions aaptOptions; private final LintOptions lintOptions; private final ExternalNativeBuild externalNativeBuild; private final DexOptions dexOptions; private final TestOptions testOptions; private final CompileOptions compileOptions; private final PackagingOptions packagingOptions; private final JacocoOptions jacoco; private final Splits splits; private final AdbOptions adbOptions; private final NamedDomainObjectContainer productFlavors; private final NamedDomainObjectContainer buildTypes; private final NamedDomainObjectContainer signingConfigs; private final List deviceProviderList = Lists.newArrayList(); private final List testServerList = Lists.newArrayList(); private final List transforms = Lists.newArrayList(); private final DataBindingOptions dataBinding; private final NamedDomainObjectContainer sourceSetsContainer; private String target; private Revision buildToolsRevision; private List libraryRequests = Lists.newArrayList(); private List flavorDimensionList; private String resourcePrefix; private ExtraModelInfo extraModelInfo; private String defaultPublishConfig = "release"; private boolean publishNonDefault = false; private Action variantFilter; protected Logger logger; private boolean isWritable = true; protected Project project; boolean generatePureSplits = false; private boolean enforceUniquePackageName = true;
下面介绍下常用的配置:
- compileSdkVersion : 编译时的版本
- buildToolsVersion : 构建工具版本
- defaultConfig{} : 默认的配置
BaseExtension中的设置源码如下,能设置的配置需要看下ProductFlavor类
public void defaultConfig(Action action) { this.checkWritability(); action.execute(this.defaultConfig); }
- buildTypes : 构建的类型,设置内容详见BuildType类
- productFlavors : 构建输入的变体,设置详见ProductFlavor类
- dexOptions : dex的设置,打包输入的文件格式。配置详见DexOptions类
- externalNativeBuild : jni开发配置文件,分为ndkBuild和cmake两种编译方式
- lintOptions : 检查代码工具的配置,利于排查代码问题,配置内容详见LintOptions类
- packagingOptions : 去除相同包操作配置
- signingConfigs :签名配置
- sourceSets : 设置资源的路径
更多相关文章
- 【Android(安卓)高性能音频】AAudio 音频流 音频设备 相关配置 (
- Android高级的总结
- Android不同分辨率的Drawable资源配置
- 使用eclipse搭建android开发环境
- java获取http:图片下载代码――android基础编
- Android入门——页面跳转
- Android(安卓)图片缩放 BitmapFactory详解
- Android(安卓)-- Intent传递对象的三种方法
- Android(安卓)P联网报错Cleartext HTTP traffic to xxx not perm