之前Android Gradle的神奇之处 ---- Gradle构建和Task引入对Task任务做了简单的介绍本节着重介绍自定义Task任务之间的联动
Project和Gradle插件
- 1 Task任务的输入输出
- 1.1 Input OutputFile
- 1.2 inputs.file outputs.files
- 2 系统内置任务
- 2.1 Zip
- 2.2 packageDebug
- 3 Task的增量构建
- 4 Project
- 4.1 ext属性扩展
- 5 Gradle插件
- 5.1 脚本插件
- 5.2 二进制插件
- 5.2.1 buidSrc
- 5.2.2 buildSrc简介
1 Task任务的输入输出
通常Task任务的输入就是某个Task任务的输出例如apk打包就经过dex打包apkbuilder压缩apk签名等每个流程的输出都是下一个流程的输出在自定义Task任务中Input和OutputFile代表当前的输入和输出
1.1 Input OutputFile
class MyTask extends DefaultTask{Inputdef inputPathOutputFiledef outFileMyTask(){group customeprintln MyTask 构造方法 配置阶段执行}TaskActiondef Action(){println MyTask 执行了}}
如果在没有指定输入和输出的情况下执行task任务会报错
Type MyTask property inputPath doesnt have a configured value.
使用Optional注解代表当前属性可选可以选择不传数据就不会报错
1.2 inputs.file outputs.files
如果不想使用1.1中的注解还可以通过其他的方式给当前的task设置输入和输出
inputs.files file(build.gradle)outputs.files file(text.txt)
使用inputs.files和outputs.files可以给当前任务输入或者输出一个文件
如果想要获取输入的文件因为当前只输入一个文件可以使用singleFile获取文件内容
inputs.files.singleFile
这里进行了一个简单的读写操作将输入文件的内容复制到了输出文件中
TaskActiondef Action(){println MyTask 执行了println inputs.files.singleFiledef inFile inputs.files.singleFiledef outFile outputs.files.singleFile//创建输出文件outFile.createNewFile()//通过text直接赋值即可outFile.text inFile.text}
2 系统内置任务
2.1 Zip
Zip是系统自带的一个zip任务能够把目标文件夹的内容打成zip包发布
task zipTask(type: Zip){//build文件夹archiveName build.zipdestinationDir project.buildDirfrom project.buildDir}
这里有几个参数需要明确一下 from待压缩的文件所在的文件夹project.buildDir为build文件夹每个模块下都有自己的build文件夹 archiveName压缩后的文件名 destinationDir压缩后的文件存放位置
2.2 packageDebug
在app工程下build/outputs下回生成对应的 debug apk 或者 release apk如果想要获取build文件夹下的outputs文件夹需要使用packageDebug任务那么首先就要获取packageDebug任务
tasks.getByName(packageDebug)
A problem occurred evaluating project :app.> Task with name packageDebug not found in project :app.
任务是在配置阶段生成的如果直接拿是拿不到的之前讲到过的钩子函数就可以帮助在任务创建之后拿任务这个时候肯定拿的到
project.afterEvaluate{//任务配置完成之后println tasks.getByName(packageDebug)task zipTask(type: Zip){//build文件夹archiveName build.zipdestinationDir project.buildDirfrom tasks.getByName(packageDebug).outputs.files}}
3 Task的增量构建
当多次执行gradle脚本构建的时候第一次所有的task任务都会执行但是如果同样的task再执行一次就不会再次执行action中的操作而是默认使用上次构建的像Task B UP-TO-DATE就是没有执行
> Task :B UP-TO-DATE> Task :AA do First> Task :finalizeTask UP-TO-DATE> Task :CC do FirstC do doLast
这就是增量构建增量构建的原理就是监控input的变化只有input发送变化了才重新执行task任务否则gradle认为可以重用之前的执行结果。
4 Project
每个moudle都对应了一个project对象因通过project对象就可以对每个项目做配置
project(:app){//这里是不支持 plugins{ } 需要applyapply plugin:com.android.applicationapply plugin:kotlin-androidapply plugin:kotlin-kaptprintln("组件化")//性能上的优化def config rootProject.ext.androidIddef dependency rootProject.ext.dependencyandroid {compileSdk config.compileSdkdefaultConfig {applicationId "com.study.modulelization"minSdk config.minSdktargetSdk config.targetSdkversionCode config.versionCodeversionName config.versionNametestInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"buildConfigField("Boolean", "isRelease", "${rootProject.isRelease}")kapt {arguments{arg("moduleName","app")}}}buildTypes {debug {buildConfigField("String", "debugUrl", "\"${rootProject.url.DEBUG} \"")}release {buildConfigField("String", "releaseUrl", "\"${rootProject.url.RELEASE}\"")minifyEnabled falseproguardFiles getDefaultProguardFile(proguard-android-optimize.txt), proguard-rules.pro}}compileOptions {sourceCompatibility JavaVersion.VERSION_1_8targetCompatibility JavaVersion.VERSION_1_8}kotlinOptions {jvmTarget 1.8}}dependencies {implementation androidx.appcompat:appcompat:1.4.1implementation com.google.android.material:material:1.5.0implementation androidx.constraintlayout:constraintlayout:2.1.3implementation project(path: :complier_api2)dependency.each { k, v -> implementation v }if (rootProject.isRelease) {//依赖包implementation project(path: :register)implementation project(path: :lay_router)kapt project(path: :lay_compiler)implementation project(:complier_api2)implementation project(:commonlib)}testImplementation junit:junit:4.androidTestImplementation androidx.test.ext:junit:1.1.3androidTestImplementation androidx.test.espresso:espresso-core:3.4.0implementation androidx.lifecycle:lifecycle-runtime-ktx:2.2.0implementation androidx.lifecycle:lifecycle-viewmodel-ktx:2.4.1implementation androidx.lifecycle:lifecycle-livedata-core-ktx:2.4.1implementation org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.2implementation org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.2}}
这里通过project(‘模块名称’)在闭包中就可以对当前模块做配置其实这样就代替了app模块中的build.gradle
通过subprojects则是可以获取到全部的子工程的project对象
4.1 ext属性扩展
ext属性扩展其实就是对project对象做属性扩展
# ext.gradleext {prop1 prop1}
在根 build.grdle中做了属性扩展实际上就是对rootProject做了扩展那么每个子模块都能拿到这个rootProject相当于在build.grdle中声明了一个变量
# 根 build.gradleproject.ext.prop2 prop2
在子模块中去获取这个变量注意是使用rootProject
# register模块 --- build.gradleprintln rootProject.prop1println rootProject.prop2输出prop1prop2
1~ 对于所有对象都可以属性扩展通过ext{ }闭包或者直接赋值 ext.prop … 2~ 由谁调用就是给谁做扩展例如project中调用就是给project做扩展一般情况下都是 3~ 在build.gradle中默认就是给当前工程的project做扩展在根build.gradle中就是给rootProject做扩展所有的moudle都可以使用这个扩展属性
5 Gradle插件
gradle插件就是提供给gradle构建工具在编译时的依赖项主要的目的就是抽取公共的构建业务达到复用的效果
像系统提供的一些任务都是剥离出来可复用的之前常见的Zip、Clean都是插件中的任务Gradle插件共分为2种接下来讲解第一种
5.1 脚本插件
脚本插件是比较常见的一种插件在之前就已经写过一些比如抽离一个压缩zip的任务可以提供给某个模块使用
# zip.gradleproject.afterEvaluate{task zipTask(type:Zip){archiveName zip01.zipdestinationDir "${project.buildDir}/custome"from tasks.getByName(packageDebug).outputs.files}}
# app/build.gradleapply from:/****/zip.gradle
通过apply的方式就完成了脚本的注入可以执行task任务
5.2 二进制插件
二进制插件就是将脚本打成jar包实现jar包依赖
# 根 build.gradleclass MyPluginTask implements Plugin{Overridevoid apply(Project target) {println MyPluginTask apply}}
二进制插件实现了Plugin接口重写apply方法在apply方法中做业务打包使用方式还是apply只不过是使用plugin作为key
# 根 build.gradleapply plugin: MyPluginTask
像这种方式是只能在一个模块中使用这个二进制插件如果想要所有的项目共享那么就需要将这个插件上传maven私服那么在使用的时候将这个插件拉取下来使用
5.2.1 buidSrc
创建一个buildSrc文件夹注意不能写错然后重新rebuild一下工程 然后需要创建一个src/main/java文件夹如果使用Java编写就创建java文件夹使用groovy编写就创建groovy文件夹
public class MyTargetPlugin implements Plugin {Overridepublic void apply(Project project) {System.out.println("这是自定义的二进制插件"project.getClass());}}
当创建这个二进制插件之后就可以在任意一个moudle中使用
# register/build.gradleapply plugin: MyTargetPlugin
我们可以看到在buildSrc的libs文件夹下有一个jar包这个jar包就可以上传到maven仓库
5.2.2 buildSrc简介
buildSrc是Android工程默认的一个插件工程有且仅有一个能够直接实现插件的封装
settingsEvaluatedprojectsLoaded> Task :buildSrc:compileJava UP-TO-DATE> Task :buildSrc:compileGroovy NO-SOURCE> Task :buildSrc:processResources> Task :buildSrc:classes> Task :buildSrc:jar> Task :buildSrc:generateSourceRoots UP-TO-DATE> Task :buildSrc:assemble> Task :buildSrc:compileTestJava NO-SOURCE> Task :buildSrc:compileTestGroovy NO-SOURCE> Task :buildSrc:processTestResources NO-SOURCE> Task :buildSrc:testClasses UP-TO-DATE> Task :buildSrc:test SKIPPED> Task :buildSrc:check SKIPPED> Task :buildSrc:build> Configure project :资源回收MyTask 构造方法 配置阶段执行
我们可以看到在Gradle配置之前就已经在编译阶段去编译这个buildSrc项目然后配置到classpath下面那么在gradle的配置阶段就可以直接使用buildSrc中生成好的插件去做操作处理
使用buildSrc的好处在于如果要修改插件内的内容可以不用等发版就直接在本地实现配置依赖不用上传maven仓库例如在插件中创建一个zip任务不需要发版在app模块中直接依赖即可
public class MyTargetPlugin implements Plugin {Overridepublic void apply(Project project) {System.out.println("这是自定义的二进制插件"project.getClass());project.afterEvaluate(new Action() {Overridepublic void execute(Project project) {File buildDir project.getBuildDir();Task packageDebug project.getTasks().getByName("packageDebug");Map 通过Java也可以实现在gradle中创建zip任务的流程就是写起来比较繁琐 # app/build.gradleapply plugin: MyTargetPlugin【文章原创作者:韩国机房 http://www.558idc.com/kt.html欢迎留下您的宝贵建议】